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 "libwebsockets.h" 28#include <mbedtls/version.h> 29 30#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x03000000) 31#define mbedtls_md5_starts_ret mbedtls_md5_starts 32#define mbedtls_md5_update_ret mbedtls_md5_update 33#define mbedtls_md5_finish_ret mbedtls_md5_finish 34#define mbedtls_sha1_finish_ret mbedtls_sha1_finish 35#define mbedtls_sha1_update_ret mbedtls_sha1_update 36#define mbedtls_sha1_starts_ret mbedtls_sha1_starts 37#define mbedtls_sha256_starts_ret mbedtls_sha256_starts 38#define mbedtls_sha256_update_ret mbedtls_sha256_update 39#define mbedtls_sha256_finish_ret mbedtls_sha256_finish 40#define mbedtls_sha512_starts_ret mbedtls_sha512_starts 41#define mbedtls_sha512_update_ret mbedtls_sha512_update 42#define mbedtls_sha512_finish_ret mbedtls_sha512_finish 43#endif 44 45#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x02070000) 46 47/* 48 * We have the _ret variants available, check the return codes on everything 49 */ 50 51int 52lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type) 53{ 54 ctx->type = (uint8_t)type; 55 56 switch (ctx->type) { 57 case LWS_GENHASH_TYPE_MD5: 58 mbedtls_md5_init(&ctx->u.md5); 59 if (mbedtls_md5_starts_ret(&ctx->u.md5)) 60 return 1; 61 break; 62 case LWS_GENHASH_TYPE_SHA1: 63 mbedtls_sha1_init(&ctx->u.sha1); 64 if (mbedtls_sha1_starts_ret(&ctx->u.sha1)) 65 return 1; 66 break; 67 case LWS_GENHASH_TYPE_SHA256: 68 mbedtls_sha256_init(&ctx->u.sha256); 69 if (mbedtls_sha256_starts_ret(&ctx->u.sha256, 0)) 70 return 1; 71 break; 72 case LWS_GENHASH_TYPE_SHA384: 73 mbedtls_sha512_init(&ctx->u.sha512); 74 if (mbedtls_sha512_starts_ret(&ctx->u.sha512, 1 /* is384 */)) 75 return 1; 76 break; 77 case LWS_GENHASH_TYPE_SHA512: 78 mbedtls_sha512_init(&ctx->u.sha512); 79 if (mbedtls_sha512_starts_ret(&ctx->u.sha512, 0)) 80 return 1; 81 break; 82 default: 83 return 1; 84 } 85 86 return 0; 87} 88 89int 90lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len) 91{ 92 if (!len) 93 return 0; 94 95 switch (ctx->type) { 96 case LWS_GENHASH_TYPE_MD5: 97 if (mbedtls_md5_update_ret(&ctx->u.md5, in, len)) 98 return 1; 99 break; 100 case LWS_GENHASH_TYPE_SHA1: 101 if (mbedtls_sha1_update_ret(&ctx->u.sha1, in, len)) 102 return 1; 103 break; 104 case LWS_GENHASH_TYPE_SHA256: 105 if (mbedtls_sha256_update_ret(&ctx->u.sha256, in, len)) 106 return 1; 107 break; 108 case LWS_GENHASH_TYPE_SHA384: 109 if (mbedtls_sha512_update_ret(&ctx->u.sha512, in, len)) 110 return 1; 111 break; 112 case LWS_GENHASH_TYPE_SHA512: 113 if (mbedtls_sha512_update_ret(&ctx->u.sha512, in, len)) 114 return 1; 115 break; 116 } 117 118 return 0; 119} 120 121int 122lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result) 123{ 124 switch (ctx->type) { 125 case LWS_GENHASH_TYPE_MD5: 126 if (mbedtls_md5_finish_ret(&ctx->u.md5, result)) 127 return 1; 128 mbedtls_md5_free(&ctx->u.md5); 129 break; 130 case LWS_GENHASH_TYPE_SHA1: 131 if (mbedtls_sha1_finish_ret(&ctx->u.sha1, result)) 132 return 1; 133 mbedtls_sha1_free(&ctx->u.sha1); 134 break; 135 case LWS_GENHASH_TYPE_SHA256: 136 if (mbedtls_sha256_finish_ret(&ctx->u.sha256, result)) 137 return 1; 138 mbedtls_sha256_free(&ctx->u.sha256); 139 break; 140 case LWS_GENHASH_TYPE_SHA384: 141 if (mbedtls_sha512_finish_ret(&ctx->u.sha512, result)) 142 return 1; 143 mbedtls_sha512_free(&ctx->u.sha512); 144 break; 145 case LWS_GENHASH_TYPE_SHA512: 146 if (mbedtls_sha512_finish_ret(&ctx->u.sha512, result)) 147 return 1; 148 mbedtls_sha512_free(&ctx->u.sha512); 149 break; 150 } 151 152 return 0; 153} 154 155#else 156 157/* 158 * mbedtls is too old to have the _ret variants 159 */ 160 161int 162lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type) 163{ 164 ctx->type = type; 165 166 switch (ctx->type) { 167 case LWS_GENHASH_TYPE_MD5: 168 mbedtls_md5_init(&ctx->u.md5); 169 mbedtls_md5_starts(&ctx->u.md5); 170 break; 171 case LWS_GENHASH_TYPE_SHA1: 172 mbedtls_sha1_init(&ctx->u.sha1); 173 mbedtls_sha1_starts(&ctx->u.sha1); 174 break; 175 case LWS_GENHASH_TYPE_SHA256: 176 mbedtls_sha256_init(&ctx->u.sha256); 177 mbedtls_sha256_starts(&ctx->u.sha256, 0); 178 break; 179 case LWS_GENHASH_TYPE_SHA384: 180 mbedtls_sha512_init(&ctx->u.sha512); 181 mbedtls_sha512_starts(&ctx->u.sha512, 1 /* is384 */); 182 break; 183 case LWS_GENHASH_TYPE_SHA512: 184 mbedtls_sha512_init(&ctx->u.sha512); 185 mbedtls_sha512_starts(&ctx->u.sha512, 0); 186 break; 187 default: 188 return 1; 189 } 190 191 return 0; 192} 193 194int 195lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len) 196{ 197 if (!len) 198 return 0; 199 200 switch (ctx->type) { 201 case LWS_GENHASH_TYPE_MD5: 202 mbedtls_md5_update(&ctx->u.md5, in, len); 203 break; 204 case LWS_GENHASH_TYPE_SHA1: 205 mbedtls_sha1_update(&ctx->u.sha1, in, len); 206 break; 207 case LWS_GENHASH_TYPE_SHA256: 208 mbedtls_sha256_update(&ctx->u.sha256, in, len); 209 break; 210 case LWS_GENHASH_TYPE_SHA384: 211 mbedtls_sha512_update(&ctx->u.sha512, in, len); 212 break; 213 case LWS_GENHASH_TYPE_SHA512: 214 mbedtls_sha512_update(&ctx->u.sha512, in, len); 215 break; 216 } 217 218 return 0; 219} 220 221int 222lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result) 223{ 224 switch (ctx->type) { 225 case LWS_GENHASH_TYPE_MD5: 226 mbedtls_md5_finish(&ctx->u.md5, result); 227 mbedtls_md5_free(&ctx->u.md5); 228 break; 229 case LWS_GENHASH_TYPE_SHA1: 230 mbedtls_sha1_finish(&ctx->u.sha1, result); 231 mbedtls_sha1_free(&ctx->u.sha1); 232 break; 233 case LWS_GENHASH_TYPE_SHA256: 234 mbedtls_sha256_finish(&ctx->u.sha256, result); 235 mbedtls_sha256_free(&ctx->u.sha256); 236 break; 237 case LWS_GENHASH_TYPE_SHA384: 238 mbedtls_sha512_finish(&ctx->u.sha512, result); 239 mbedtls_sha512_free(&ctx->u.sha512); 240 break; 241 case LWS_GENHASH_TYPE_SHA512: 242 mbedtls_sha512_finish(&ctx->u.sha512, result); 243 mbedtls_sha512_free(&ctx->u.sha512); 244 break; 245 } 246 247 return 0; 248} 249 250#endif 251 252int 253lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, 254 const uint8_t *key, size_t key_len) 255{ 256 int t; 257 258 ctx->type = (uint8_t)type; 259 260 switch (type) { 261 case LWS_GENHMAC_TYPE_SHA256: 262 t = MBEDTLS_MD_SHA256; 263 break; 264 case LWS_GENHMAC_TYPE_SHA384: 265 t = MBEDTLS_MD_SHA384; 266 break; 267 case LWS_GENHMAC_TYPE_SHA512: 268 t = MBEDTLS_MD_SHA512; 269 break; 270 default: 271 return -1; 272 } 273 274 ctx->hmac = mbedtls_md_info_from_type((mbedtls_md_type_t)t); 275 if (!ctx->hmac) 276 return -1; 277 278#if !defined(LWS_HAVE_mbedtls_md_setup) 279 if (mbedtls_md_init_ctx(&ctx->ctx, ctx->hmac)) 280 return -1; 281#else 282 if (mbedtls_md_setup(&ctx->ctx, ctx->hmac, 1)) 283 return -1; 284#endif 285 286 if (mbedtls_md_hmac_starts(&ctx->ctx, key, key_len)) { 287 mbedtls_md_free(&ctx->ctx); 288 ctx->hmac = NULL; 289 290 return -1; 291 } 292 293 return 0; 294} 295 296int 297lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len) 298{ 299 if (!len) 300 return 0; 301 302 if (mbedtls_md_hmac_update(&ctx->ctx, in, len)) 303 return -1; 304 305 return 0; 306} 307 308int 309lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result) 310{ 311 int n = 0; 312 313 if (result) 314 n = mbedtls_md_hmac_finish(&ctx->ctx, result); 315 316 mbedtls_md_free(&ctx->ctx); 317 ctx->hmac = NULL; 318 if (n) 319 return -1; 320 321 return 0; 322} 323