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