1/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay@cryptsoft.com). 6 * The implementation was written so as to conform with Netscapes SSL. 7 * 8 * This library is free for commercial and non-commercial use as long as 9 * the following conditions are aheared to. The following conditions 10 * apply to all code found in this distribution, be it the RC4, RSA, 11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12 * included with this distribution is covered by the same copyright terms 13 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 14 * 15 * Copyright remains Eric Young's, and as such any Copyright notices in 16 * the code are not to be removed. 17 * If this package is used in a product, Eric Young should be given attribution 18 * as the author of the parts of the library used. 19 * This can be in the form of a textual message at program startup or 20 * in documentation (online or textual) provided with the package. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * "This product includes cryptographic software written by 33 * Eric Young (eay@cryptsoft.com)" 34 * The word 'cryptographic' can be left out if the rouines from the library 35 * being used are not cryptographic related :-). 36 * 4. If you include any Windows specific code (or a derivative thereof) from 37 * the apps directory (application code) you must include an acknowledgement: 38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * The licence and distribution terms for any publically available version or 53 * derivative of this code cannot be changed. i.e. this code cannot simply be 54 * copied and put under another distribution licence 55 * [including the GNU Public Licence.] */ 56 57#include <openssl/digest.h> 58 59#include <assert.h> 60#include <string.h> 61 62#include <openssl/err.h> 63#include <openssl/obj.h> 64#include <openssl/mem.h> 65 66#include "internal.h" 67 68 69int EVP_MD_type(const EVP_MD *md) { return md->type; } 70 71const char *EVP_MD_name(const EVP_MD *md) { return OBJ_nid2sn(md->type); } 72 73uint32_t EVP_MD_flags(const EVP_MD *md) { return md->flags; } 74 75size_t EVP_MD_size(const EVP_MD *md) { return md->md_size; } 76 77size_t EVP_MD_block_size(const EVP_MD *md) { return md->block_size; } 78 79 80void EVP_MD_CTX_init(EVP_MD_CTX *ctx) { memset(ctx, 0, sizeof(EVP_MD_CTX)); } 81 82EVP_MD_CTX *EVP_MD_CTX_create(void) { 83 EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX)); 84 85 if (ctx) { 86 EVP_MD_CTX_init(ctx); 87 } 88 89 return ctx; 90} 91 92int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) { 93 if (ctx->digest && ctx->digest->ctx_size && ctx->md_data) { 94 OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); 95 OPENSSL_free(ctx->md_data); 96 } 97 98 assert(ctx->pctx == NULL || ctx->pctx_ops != NULL); 99 if (ctx->pctx_ops) { 100 ctx->pctx_ops->free(ctx->pctx); 101 } 102 103 EVP_MD_CTX_init(ctx); 104 105 return 1; 106} 107 108void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) { 109 if (!ctx) { 110 return; 111 } 112 113 EVP_MD_CTX_cleanup(ctx); 114 OPENSSL_free(ctx); 115} 116 117int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) { 118 uint8_t *tmp_buf = NULL; 119 120 if (in == NULL || in->digest == NULL) { 121 OPENSSL_PUT_ERROR(DIGEST, EVP_MD_CTX_copy_ex, 122 DIGEST_R_INPUT_NOT_INITIALIZED); 123 return 0; 124 } 125 126 if (out->digest == in->digest) { 127 /* |md_data| will be the correct size in this case so it's removed from 128 * |out| at this point so that |EVP_MD_CTX_cleanup| doesn't free it and 129 * then it's reused. */ 130 tmp_buf = out->md_data; 131 out->md_data = NULL; 132 } 133 134 EVP_MD_CTX_cleanup(out); 135 memcpy(out, in, sizeof(EVP_MD_CTX)); 136 137 if (in->md_data && in->digest->ctx_size) { 138 if (tmp_buf) { 139 out->md_data = tmp_buf; 140 } else { 141 out->md_data = OPENSSL_malloc(in->digest->ctx_size); 142 if (!out->md_data) { 143 OPENSSL_PUT_ERROR(DIGEST, EVP_MD_CTX_copy_ex, ERR_R_MALLOC_FAILURE); 144 return 0; 145 } 146 } 147 memcpy(out->md_data, in->md_data, in->digest->ctx_size); 148 } 149 150 assert(in->pctx == NULL || in->pctx_ops != NULL); 151 if (in->pctx && in->pctx_ops) { 152 out->pctx = in->pctx_ops->dup(in->pctx); 153 if (!out->pctx) { 154 EVP_MD_CTX_cleanup(out); 155 return 0; 156 } 157 } 158 159 return 1; 160} 161 162int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) { 163 EVP_MD_CTX_init(out); 164 return EVP_MD_CTX_copy_ex(out, in); 165} 166 167int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *engine) { 168 if (ctx->digest != type) { 169 if (ctx->digest && ctx->digest->ctx_size) { 170 OPENSSL_free(ctx->md_data); 171 } 172 ctx->digest = type; 173 if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) { 174 ctx->update = type->update; 175 ctx->md_data = OPENSSL_malloc(type->ctx_size); 176 if (ctx->md_data == NULL) { 177 OPENSSL_PUT_ERROR(DIGEST, EVP_DigestInit_ex, ERR_R_MALLOC_FAILURE); 178 return 0; 179 } 180 } 181 } 182 183 assert(ctx->pctx == NULL || ctx->pctx_ops != NULL); 184 if (ctx->pctx_ops) { 185 if (!ctx->pctx_ops->begin_digest(ctx)) { 186 return 0; 187 } 188 } 189 190 if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) { 191 return 1; 192 } 193 194 return ctx->digest->init(ctx); 195} 196 197int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) { 198 EVP_MD_CTX_init(ctx); 199 return EVP_DigestInit_ex(ctx, type, NULL); 200} 201 202int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) { 203 return ctx->update(ctx, data, len); 204} 205 206int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, unsigned int *size) { 207 int ret; 208 209 assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE); 210 ret = ctx->digest->final(ctx, md_out); 211 if (size != NULL) { 212 *size = ctx->digest->md_size; 213 } 214 OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); 215 216 return ret; 217} 218 219int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md, unsigned int *size) { 220 int ret = EVP_DigestFinal_ex(ctx, md, size); 221 EVP_MD_CTX_cleanup(ctx); 222 return ret; 223} 224 225int EVP_Digest(const void *data, size_t count, uint8_t *out_md, 226 unsigned int *out_size, const EVP_MD *type, ENGINE *impl) { 227 EVP_MD_CTX ctx; 228 int ret; 229 230 EVP_MD_CTX_init(&ctx); 231 ret = EVP_DigestInit_ex(&ctx, type, impl) && 232 EVP_DigestUpdate(&ctx, data, count) && 233 EVP_DigestFinal_ex(&ctx, out_md, out_size); 234 EVP_MD_CTX_cleanup(&ctx); 235 236 return ret; 237} 238 239 240const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) { 241 if (ctx == NULL) { 242 return NULL; 243 } 244 return ctx->digest; 245} 246 247unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx) { 248 return EVP_MD_size(EVP_MD_CTX_md(ctx)); 249} 250 251unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) { 252 return EVP_MD_block_size(EVP_MD_CTX_md(ctx)); 253} 254 255int EVP_MD_CTX_type(const EVP_MD_CTX *ctx) { 256 return EVP_MD_type(EVP_MD_CTX_md(ctx)); 257} 258 259void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, uint32_t flags) { 260 ctx->flags |= flags; 261} 262 263void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, uint32_t flags) { 264 ctx->flags &= ~flags; 265} 266 267uint32_t EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, uint32_t flags) { 268 return ctx->flags & flags; 269} 270 271int EVP_add_digest(const EVP_MD *digest) { 272 return 1; 273} 274