1 /* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 * 24 * lws_genhash provides a hash / hmac abstraction api in lws that works the 25 * same whether you are using openssl or mbedtls hash functions underneath. 26 */ 27#include <private-lib-core.h> 28#include <openssl/obj_mac.h> 29#include <openssl/opensslv.h> 30/* 31 * Care: many openssl apis return 1 for success. These are translated to the 32 * lws convention of 0 for success. 33 */ 34 35int 36lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type) 37{ 38 ctx->type = (uint8_t)type; 39 ctx->mdctx = EVP_MD_CTX_create(); 40 if (!ctx->mdctx) 41 return 1; 42 43 switch (ctx->type) { 44 case LWS_GENHASH_TYPE_MD5: 45 ctx->evp_type = EVP_md5(); 46 break; 47 case LWS_GENHASH_TYPE_SHA1: 48 ctx->evp_type = EVP_sha1(); 49 break; 50 case LWS_GENHASH_TYPE_SHA256: 51 ctx->evp_type = EVP_sha256(); 52 break; 53 case LWS_GENHASH_TYPE_SHA384: 54 ctx->evp_type = EVP_sha384(); 55 break; 56 case LWS_GENHASH_TYPE_SHA512: 57 ctx->evp_type = EVP_sha512(); 58 break; 59 default: 60 return 1; 61 } 62 63 if (EVP_DigestInit_ex(ctx->mdctx, ctx->evp_type, NULL) != 1) { 64 EVP_MD_CTX_destroy(ctx->mdctx); 65 66 return 1; 67 } 68 69 return 0; 70} 71 72int 73lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len) 74{ 75 if (!len) 76 return 0; 77 78 return EVP_DigestUpdate(ctx->mdctx, in, len) != 1; 79} 80 81int 82lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result) 83{ 84 unsigned int len; 85 int ret = 0; 86 87 if (!ctx->mdctx) 88 return 0; 89 90 if (result) 91 ret = EVP_DigestFinal_ex(ctx->mdctx, result, &len) != 1; 92 93 (void)len; 94 95 EVP_MD_CTX_destroy(ctx->mdctx); 96 ctx->mdctx = NULL; 97 98 return ret; 99} 100 101#if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key) 102 103int 104lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, 105 const uint8_t *key, size_t key_len) 106{ 107 ctx->ctx = EVP_MD_CTX_create(); 108 if (!ctx->ctx) 109 return -1; 110 111 ctx->evp_type = 0; 112 ctx->type = (uint8_t)type; 113 114 switch (type) { 115 case LWS_GENHMAC_TYPE_SHA256: 116 ctx->evp_type = EVP_sha256(); 117 break; 118 case LWS_GENHMAC_TYPE_SHA384: 119 ctx->evp_type = EVP_sha384(); 120 break; 121 case LWS_GENHMAC_TYPE_SHA512: 122 ctx->evp_type = EVP_sha512(); 123 break; 124 default: 125 lwsl_err("%s: unknown HMAC type %d\n", __func__, type); 126 goto bail; 127 } 128 129 ctx->key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, key_len); 130 if (!ctx->key) 131 goto bail; 132 133 if (EVP_DigestSignInit(ctx->ctx, NULL, ctx->evp_type, NULL, ctx->key) != 1) 134 goto bail1; 135 136 return 0; 137 138bail1: 139 EVP_PKEY_free(ctx->key); 140bail: 141 EVP_MD_CTX_free(ctx->ctx); 142 143 return -1; 144} 145 146int 147lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len) 148{ 149 150 if (EVP_DigestSignUpdate(ctx->ctx, in, len) != 1) 151 return -1; 152 153 return 0; 154} 155 156int 157lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result) 158{ 159 size_t size = (size_t)lws_genhmac_size(ctx->type); 160 int n; 161 162 n = EVP_DigestSignFinal(ctx->ctx, result, &size); 163 EVP_MD_CTX_free(ctx->ctx); 164 EVP_PKEY_free(ctx->key); 165 166 if (n != 1) 167 return -1; 168 169 return 0; 170} 171 172#else 173 174int 175lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, 176 const uint8_t *key, size_t key_len) 177{ 178#if defined(LWS_HAVE_HMAC_CTX_new) 179 ctx->ctx = HMAC_CTX_new(); 180 if (!ctx->ctx) 181 return -1; 182#else 183 HMAC_CTX_init(&ctx->ctx); 184#endif 185 186 ctx->evp_type = 0; 187 ctx->type = (uint8_t)type; 188 189 switch (type) { 190 case LWS_GENHMAC_TYPE_SHA256: 191 ctx->evp_type = EVP_sha256(); 192 break; 193 case LWS_GENHMAC_TYPE_SHA384: 194 ctx->evp_type = EVP_sha384(); 195 break; 196 case LWS_GENHMAC_TYPE_SHA512: 197 ctx->evp_type = EVP_sha512(); 198 break; 199 default: 200 lwsl_err("%s: unknown HMAC type %d\n", __func__, type); 201 goto bail; 202 } 203 204#if defined(LWS_HAVE_HMAC_CTX_new) 205 if (HMAC_Init_ex(ctx->ctx, key, (int)key_len, ctx->evp_type, NULL) != 1) 206#else 207 if (HMAC_Init_ex(&ctx->ctx, key, (int)key_len, ctx->evp_type, NULL) != 1) 208#endif 209 goto bail; 210 211 return 0; 212 213bail: 214#if defined(LWS_HAVE_HMAC_CTX_new) 215 HMAC_CTX_free(ctx->ctx); 216#endif 217 218 return -1; 219} 220 221int 222lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len) 223{ 224#if defined(LWS_HAVE_HMAC_CTX_new) 225#if defined(LIBRESSL_VERSION_NUMBER) 226 if (HMAC_Update(ctx->ctx, in, len) != 1) 227#else 228 if (HMAC_Update(ctx->ctx, in, (int)len) != 1) 229#endif 230#else /* HMAC_CTX_new */ 231 if (HMAC_Update(&ctx->ctx, in, len) != 1) 232#endif 233 return -1; 234 235 return 0; 236} 237 238int 239lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result) 240{ 241 unsigned int size = (unsigned int)lws_genhmac_size(ctx->type); 242#if defined(LWS_HAVE_HMAC_CTX_new) 243 int n = HMAC_Final(ctx->ctx, result, &size); 244 245 HMAC_CTX_free(ctx->ctx); 246#else 247 int n = HMAC_Final(&ctx->ctx, result, &size); 248#endif 249 250 if (n != 1) 251 return -1; 252 253 return 0; 254} 255 256 257#endif 258