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 */ 28static OSSL_FUNC_mac_newctx_fn siphash_new; 29static OSSL_FUNC_mac_dupctx_fn siphash_dup; 30static OSSL_FUNC_mac_freectx_fn siphash_free; 31static OSSL_FUNC_mac_gettable_ctx_params_fn siphash_gettable_ctx_params; 32static OSSL_FUNC_mac_get_ctx_params_fn siphash_get_ctx_params; 33static OSSL_FUNC_mac_settable_ctx_params_fn siphash_settable_ctx_params; 34static OSSL_FUNC_mac_set_ctx_params_fn siphash_set_params; 35static OSSL_FUNC_mac_init_fn siphash_init; 36static OSSL_FUNC_mac_update_fn siphash_update; 37static OSSL_FUNC_mac_final_fn siphash_final; 38 39struct 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 46static unsigned int crounds(struct siphash_data_st *ctx) 47{ 48 return ctx->crounds != 0 ? ctx->crounds : SIPHASH_C_ROUNDS; 49} 50 51static unsigned int drounds(struct siphash_data_st *ctx) 52{ 53 return ctx->drounds != 0 ? ctx->drounds : SIPHASH_D_ROUNDS; 54} 55 56static 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 68static void siphash_free(void *vmacctx) 69{ 70 OPENSSL_free(vmacctx); 71} 72 73static 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 88static size_t siphash_size(void *vmacctx) 89{ 90 struct siphash_data_st *ctx = vmacctx; 91 92 return SipHash_hash_size(&ctx->siphash); 93} 94 95static 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 108static 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 126static 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 138static 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 151static 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 164static 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 181static 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 195static 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 223const 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