1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <errno.h> 12e1051a39Sopenharmony_ci#include <openssl/buffer.h> 13e1051a39Sopenharmony_ci#include <openssl/evp.h> 14e1051a39Sopenharmony_ci#include "internal/bio.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci/* 17e1051a39Sopenharmony_ci * BIO_put and BIO_get both add to the digest, BIO_gets returns the digest 18e1051a39Sopenharmony_ci */ 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_cistatic int md_write(BIO *h, char const *buf, int num); 21e1051a39Sopenharmony_cistatic int md_read(BIO *h, char *buf, int size); 22e1051a39Sopenharmony_cistatic int md_gets(BIO *h, char *str, int size); 23e1051a39Sopenharmony_cistatic long md_ctrl(BIO *h, int cmd, long arg1, void *arg2); 24e1051a39Sopenharmony_cistatic int md_new(BIO *h); 25e1051a39Sopenharmony_cistatic int md_free(BIO *data); 26e1051a39Sopenharmony_cistatic long md_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_cistatic const BIO_METHOD methods_md = { 29e1051a39Sopenharmony_ci BIO_TYPE_MD, 30e1051a39Sopenharmony_ci "message digest", 31e1051a39Sopenharmony_ci bwrite_conv, 32e1051a39Sopenharmony_ci md_write, 33e1051a39Sopenharmony_ci bread_conv, 34e1051a39Sopenharmony_ci md_read, 35e1051a39Sopenharmony_ci NULL, /* md_puts, */ 36e1051a39Sopenharmony_ci md_gets, 37e1051a39Sopenharmony_ci md_ctrl, 38e1051a39Sopenharmony_ci md_new, 39e1051a39Sopenharmony_ci md_free, 40e1051a39Sopenharmony_ci md_callback_ctrl, 41e1051a39Sopenharmony_ci}; 42e1051a39Sopenharmony_ci 43e1051a39Sopenharmony_ciconst BIO_METHOD *BIO_f_md(void) 44e1051a39Sopenharmony_ci{ 45e1051a39Sopenharmony_ci return &methods_md; 46e1051a39Sopenharmony_ci} 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_cistatic int md_new(BIO *bi) 49e1051a39Sopenharmony_ci{ 50e1051a39Sopenharmony_ci EVP_MD_CTX *ctx; 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ci ctx = EVP_MD_CTX_new(); 53e1051a39Sopenharmony_ci if (ctx == NULL) 54e1051a39Sopenharmony_ci return 0; 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci BIO_set_init(bi, 1); 57e1051a39Sopenharmony_ci BIO_set_data(bi, ctx); 58e1051a39Sopenharmony_ci 59e1051a39Sopenharmony_ci return 1; 60e1051a39Sopenharmony_ci} 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_cistatic int md_free(BIO *a) 63e1051a39Sopenharmony_ci{ 64e1051a39Sopenharmony_ci if (a == NULL) 65e1051a39Sopenharmony_ci return 0; 66e1051a39Sopenharmony_ci EVP_MD_CTX_free(BIO_get_data(a)); 67e1051a39Sopenharmony_ci BIO_set_data(a, NULL); 68e1051a39Sopenharmony_ci BIO_set_init(a, 0); 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci return 1; 71e1051a39Sopenharmony_ci} 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_cistatic int md_read(BIO *b, char *out, int outl) 74e1051a39Sopenharmony_ci{ 75e1051a39Sopenharmony_ci int ret = 0; 76e1051a39Sopenharmony_ci EVP_MD_CTX *ctx; 77e1051a39Sopenharmony_ci BIO *next; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci if (out == NULL) 80e1051a39Sopenharmony_ci return 0; 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ci ctx = BIO_get_data(b); 83e1051a39Sopenharmony_ci next = BIO_next(b); 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ci if ((ctx == NULL) || (next == NULL)) 86e1051a39Sopenharmony_ci return 0; 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci ret = BIO_read(next, out, outl); 89e1051a39Sopenharmony_ci if (BIO_get_init(b)) { 90e1051a39Sopenharmony_ci if (ret > 0) { 91e1051a39Sopenharmony_ci if (EVP_DigestUpdate(ctx, (unsigned char *)out, 92e1051a39Sopenharmony_ci (unsigned int)ret) <= 0) 93e1051a39Sopenharmony_ci return -1; 94e1051a39Sopenharmony_ci } 95e1051a39Sopenharmony_ci } 96e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 97e1051a39Sopenharmony_ci BIO_copy_next_retry(b); 98e1051a39Sopenharmony_ci return ret; 99e1051a39Sopenharmony_ci} 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_cistatic int md_write(BIO *b, const char *in, int inl) 102e1051a39Sopenharmony_ci{ 103e1051a39Sopenharmony_ci int ret = 0; 104e1051a39Sopenharmony_ci EVP_MD_CTX *ctx; 105e1051a39Sopenharmony_ci BIO *next; 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci if ((in == NULL) || (inl <= 0)) 108e1051a39Sopenharmony_ci return 0; 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci ctx = BIO_get_data(b); 111e1051a39Sopenharmony_ci next = BIO_next(b); 112e1051a39Sopenharmony_ci if ((ctx != NULL) && (next != NULL)) 113e1051a39Sopenharmony_ci ret = BIO_write(next, in, inl); 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci if (BIO_get_init(b)) { 116e1051a39Sopenharmony_ci if (ret > 0) { 117e1051a39Sopenharmony_ci if (!EVP_DigestUpdate(ctx, (const unsigned char *)in, 118e1051a39Sopenharmony_ci (unsigned int)ret)) { 119e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 120e1051a39Sopenharmony_ci return 0; 121e1051a39Sopenharmony_ci } 122e1051a39Sopenharmony_ci } 123e1051a39Sopenharmony_ci } 124e1051a39Sopenharmony_ci if (next != NULL) { 125e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 126e1051a39Sopenharmony_ci BIO_copy_next_retry(b); 127e1051a39Sopenharmony_ci } 128e1051a39Sopenharmony_ci return ret; 129e1051a39Sopenharmony_ci} 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_cistatic long md_ctrl(BIO *b, int cmd, long num, void *ptr) 132e1051a39Sopenharmony_ci{ 133e1051a39Sopenharmony_ci EVP_MD_CTX *ctx, *dctx, **pctx; 134e1051a39Sopenharmony_ci const EVP_MD **ppmd; 135e1051a39Sopenharmony_ci EVP_MD *md; 136e1051a39Sopenharmony_ci long ret = 1; 137e1051a39Sopenharmony_ci BIO *dbio, *next; 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci ctx = BIO_get_data(b); 141e1051a39Sopenharmony_ci next = BIO_next(b); 142e1051a39Sopenharmony_ci 143e1051a39Sopenharmony_ci switch (cmd) { 144e1051a39Sopenharmony_ci case BIO_CTRL_RESET: 145e1051a39Sopenharmony_ci if (BIO_get_init(b)) 146e1051a39Sopenharmony_ci ret = EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL); 147e1051a39Sopenharmony_ci else 148e1051a39Sopenharmony_ci ret = 0; 149e1051a39Sopenharmony_ci if (ret > 0) 150e1051a39Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 151e1051a39Sopenharmony_ci break; 152e1051a39Sopenharmony_ci case BIO_C_GET_MD: 153e1051a39Sopenharmony_ci if (BIO_get_init(b)) { 154e1051a39Sopenharmony_ci ppmd = ptr; 155e1051a39Sopenharmony_ci *ppmd = EVP_MD_CTX_get0_md(ctx); 156e1051a39Sopenharmony_ci } else 157e1051a39Sopenharmony_ci ret = 0; 158e1051a39Sopenharmony_ci break; 159e1051a39Sopenharmony_ci case BIO_C_GET_MD_CTX: 160e1051a39Sopenharmony_ci pctx = ptr; 161e1051a39Sopenharmony_ci *pctx = ctx; 162e1051a39Sopenharmony_ci BIO_set_init(b, 1); 163e1051a39Sopenharmony_ci break; 164e1051a39Sopenharmony_ci case BIO_C_SET_MD_CTX: 165e1051a39Sopenharmony_ci if (BIO_get_init(b)) 166e1051a39Sopenharmony_ci BIO_set_data(b, ptr); 167e1051a39Sopenharmony_ci else 168e1051a39Sopenharmony_ci ret = 0; 169e1051a39Sopenharmony_ci break; 170e1051a39Sopenharmony_ci case BIO_C_DO_STATE_MACHINE: 171e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 172e1051a39Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 173e1051a39Sopenharmony_ci BIO_copy_next_retry(b); 174e1051a39Sopenharmony_ci break; 175e1051a39Sopenharmony_ci 176e1051a39Sopenharmony_ci case BIO_C_SET_MD: 177e1051a39Sopenharmony_ci md = ptr; 178e1051a39Sopenharmony_ci ret = EVP_DigestInit_ex(ctx, md, NULL); 179e1051a39Sopenharmony_ci if (ret > 0) 180e1051a39Sopenharmony_ci BIO_set_init(b, 1); 181e1051a39Sopenharmony_ci break; 182e1051a39Sopenharmony_ci case BIO_CTRL_DUP: 183e1051a39Sopenharmony_ci dbio = ptr; 184e1051a39Sopenharmony_ci dctx = BIO_get_data(dbio); 185e1051a39Sopenharmony_ci if (!EVP_MD_CTX_copy_ex(dctx, ctx)) 186e1051a39Sopenharmony_ci return 0; 187e1051a39Sopenharmony_ci BIO_set_init(b, 1); 188e1051a39Sopenharmony_ci break; 189e1051a39Sopenharmony_ci default: 190e1051a39Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 191e1051a39Sopenharmony_ci break; 192e1051a39Sopenharmony_ci } 193e1051a39Sopenharmony_ci return ret; 194e1051a39Sopenharmony_ci} 195e1051a39Sopenharmony_ci 196e1051a39Sopenharmony_cistatic long md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 197e1051a39Sopenharmony_ci{ 198e1051a39Sopenharmony_ci BIO *next; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci next = BIO_next(b); 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ci if (next == NULL) 203e1051a39Sopenharmony_ci return 0; 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ci return BIO_callback_ctrl(next, cmd, fp); 206e1051a39Sopenharmony_ci} 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_cistatic int md_gets(BIO *bp, char *buf, int size) 209e1051a39Sopenharmony_ci{ 210e1051a39Sopenharmony_ci EVP_MD_CTX *ctx; 211e1051a39Sopenharmony_ci unsigned int ret; 212e1051a39Sopenharmony_ci 213e1051a39Sopenharmony_ci ctx = BIO_get_data(bp); 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_ci if (size < EVP_MD_CTX_get_size(ctx)) 216e1051a39Sopenharmony_ci return 0; 217e1051a39Sopenharmony_ci 218e1051a39Sopenharmony_ci if (EVP_DigestFinal_ex(ctx, (unsigned char *)buf, &ret) <= 0) 219e1051a39Sopenharmony_ci return -1; 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci return (int)ret; 222e1051a39Sopenharmony_ci} 223