1 /* 2 * Copyright 2018-2022 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 <string.h> 11 #include <openssl/core_dispatch.h> 12 #include <openssl/core_names.h> 13 #include <openssl/params.h> 14 #include <openssl/evp.h> 15 #include <openssl/err.h> 16 #include <openssl/proverr.h> 17 18 #include "crypto/siphash.h" 19 20 #include "prov/implementations.h" 21 #include "prov/providercommon.h" 22 23 /* 24 * Forward declaration of everything implemented here. This is not strictly 25 * necessary for the compiler, but provides an assurance that the signatures 26 * of the functions in the dispatch table are correct. 27 */ 28 static OSSL_FUNC_mac_newctx_fn siphash_new; 29 static OSSL_FUNC_mac_dupctx_fn siphash_dup; 30 static OSSL_FUNC_mac_freectx_fn siphash_free; 31 static OSSL_FUNC_mac_gettable_ctx_params_fn siphash_gettable_ctx_params; 32 static OSSL_FUNC_mac_get_ctx_params_fn siphash_get_ctx_params; 33 static OSSL_FUNC_mac_settable_ctx_params_fn siphash_settable_ctx_params; 34 static OSSL_FUNC_mac_set_ctx_params_fn siphash_set_params; 35 static OSSL_FUNC_mac_init_fn siphash_init; 36 static OSSL_FUNC_mac_update_fn siphash_update; 37 static OSSL_FUNC_mac_final_fn siphash_final; 38 39 struct siphash_data_st { 40 void *provctx; 41 SIPHASH siphash; /* Siphash data */ 42 SIPHASH sipcopy; /* Siphash data copy for reinitialization */ 43 unsigned int crounds, drounds; 44 }; 45 46 static unsigned int crounds(struct siphash_data_st *ctx) 47 { 48 return ctx->crounds != 0 ? ctx->crounds : SIPHASH_C_ROUNDS; 49 } 50 51 static unsigned int drounds(struct siphash_data_st *ctx) 52 { 53 return ctx->drounds != 0 ? ctx->drounds : SIPHASH_D_ROUNDS; 54 } 55 56 static void *siphash_new(void *provctx) 57 { 58 struct siphash_data_st *ctx; 59 60 if (!ossl_prov_is_running()) 61 return NULL; 62 ctx = OPENSSL_zalloc(sizeof(*ctx)); 63 if (ctx != NULL) 64 ctx->provctx = provctx; 65 return ctx; 66 } 67 68 static void siphash_free(void *vmacctx) 69 { 70 OPENSSL_free(vmacctx); 71 } 72 73 static void *siphash_dup(void *vsrc) 74 { 75 struct siphash_data_st *ssrc = vsrc; 76 struct siphash_data_st *sdst; 77 78 if (!ossl_prov_is_running()) 79 return NULL; 80 sdst = OPENSSL_malloc(sizeof(*sdst)); 81 if (sdst == NULL) 82 return NULL; 83 84 *sdst = *ssrc; 85 return sdst; 86 } 87 88 static size_t siphash_size(void *vmacctx) 89 { 90 struct siphash_data_st *ctx = vmacctx; 91 92 return SipHash_hash_size(&ctx->siphash); 93 } 94 95 static int siphash_setkey(struct siphash_data_st *ctx, 96 const unsigned char *key, size_t keylen) 97 { 98 int ret; 99 100 if (keylen != SIPHASH_KEY_SIZE) 101 return 0; 102 ret = SipHash_Init(&ctx->siphash, key, crounds(ctx), drounds(ctx)); 103 if (ret) 104 ctx->sipcopy = ctx->siphash; 105 return ret; 106 } 107 108 static int siphash_init(void *vmacctx, const unsigned char *key, size_t keylen, 109 const OSSL_PARAM params[]) 110 { 111 struct siphash_data_st *ctx = vmacctx; 112 113 if (!ossl_prov_is_running() || !siphash_set_params(ctx, params)) 114 return 0; 115 /* 116 * Without a key, there is not much to do here, 117 * The actual initialization happens through controls. 118 */ 119 if (key == NULL) { 120 ctx->siphash = ctx->sipcopy; 121 return 1; 122 } 123 return siphash_setkey(ctx, key, keylen); 124 } 125 126 static int siphash_update(void *vmacctx, const unsigned char *data, 127 size_t datalen) 128 { 129 struct siphash_data_st *ctx = vmacctx; 130 131 if (datalen == 0) 132 return 1; 133 134 SipHash_Update(&ctx->siphash, data, datalen); 135 return 1; 136 } 137 138 static int siphash_final(void *vmacctx, unsigned char *out, size_t *outl, 139 size_t outsize) 140 { 141 struct siphash_data_st *ctx = vmacctx; 142 size_t hlen = siphash_size(ctx); 143 144 if (!ossl_prov_is_running() || outsize < hlen) 145 return 0; 146 147 *outl = hlen; 148 return SipHash_Final(&ctx->siphash, out, hlen); 149 } 150 151 static const OSSL_PARAM *siphash_gettable_ctx_params(ossl_unused void *ctx, 152 ossl_unused void *provctx) 153 { 154 static const OSSL_PARAM known_gettable_ctx_params[] = { 155 OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), 156 OSSL_PARAM_uint(OSSL_MAC_PARAM_C_ROUNDS, NULL), 157 OSSL_PARAM_uint(OSSL_MAC_PARAM_D_ROUNDS, NULL), 158 OSSL_PARAM_END 159 }; 160 161 return known_gettable_ctx_params; 162 } 163 164 static int siphash_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) 165 { 166 struct siphash_data_st *ctx = vmacctx; 167 OSSL_PARAM *p; 168 169 if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL 170 && !OSSL_PARAM_set_size_t(p, siphash_size(vmacctx))) 171 return 0; 172 if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_C_ROUNDS)) != NULL 173 && !OSSL_PARAM_set_uint(p, crounds(ctx))) 174 return 0; 175 if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_D_ROUNDS)) != NULL 176 && !OSSL_PARAM_set_uint(p, drounds(ctx))) 177 return 0; 178 return 1; 179 } 180 181 static const OSSL_PARAM *siphash_settable_ctx_params(ossl_unused void *ctx, 182 void *provctx) 183 { 184 static const OSSL_PARAM known_settable_ctx_params[] = { 185 OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), 186 OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), 187 OSSL_PARAM_uint(OSSL_MAC_PARAM_C_ROUNDS, NULL), 188 OSSL_PARAM_uint(OSSL_MAC_PARAM_D_ROUNDS, NULL), 189 OSSL_PARAM_END 190 }; 191 192 return known_settable_ctx_params; 193 } 194 195 static int siphash_set_params(void *vmacctx, const OSSL_PARAM *params) 196 { 197 struct siphash_data_st *ctx = vmacctx; 198 const OSSL_PARAM *p = NULL; 199 size_t size; 200 201 if (params == NULL) 202 return 1; 203 204 if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) { 205 if (!OSSL_PARAM_get_size_t(p, &size) 206 || !SipHash_set_hash_size(&ctx->siphash, size) 207 || !SipHash_set_hash_size(&ctx->sipcopy, size)) 208 return 0; 209 } 210 if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_C_ROUNDS)) != NULL 211 && !OSSL_PARAM_get_uint(p, &ctx->crounds)) 212 return 0; 213 if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_D_ROUNDS)) != NULL 214 && !OSSL_PARAM_get_uint(p, &ctx->drounds)) 215 return 0; 216 if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) 217 if (p->data_type != OSSL_PARAM_OCTET_STRING 218 || !siphash_setkey(ctx, p->data, p->data_size)) 219 return 0; 220 return 1; 221 } 222 223 const OSSL_DISPATCH ossl_siphash_functions[] = { 224 { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))siphash_new }, 225 { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))siphash_dup }, 226 { OSSL_FUNC_MAC_FREECTX, (void (*)(void))siphash_free }, 227 { OSSL_FUNC_MAC_INIT, (void (*)(void))siphash_init }, 228 { OSSL_FUNC_MAC_UPDATE, (void (*)(void))siphash_update }, 229 { OSSL_FUNC_MAC_FINAL, (void (*)(void))siphash_final }, 230 { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, 231 (void (*)(void))siphash_gettable_ctx_params }, 232 { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))siphash_get_ctx_params }, 233 { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, 234 (void (*)(void))siphash_settable_ctx_params }, 235 { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))siphash_set_params }, 236 { 0, NULL } 237 }; 238