1/* 2 * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 4 * 5 * Licensed under the Apache License 2.0 (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or at 8 * https://www.openssl.org/source/license.html 9 */ 10 11#include <string.h> 12#include <openssl/err.h> 13#include <openssl/cryptoerr.h> 14#include <openssl/params.h> 15#include <openssl/types.h> 16#include <openssl/safestack.h> 17#include "internal/param_build_set.h" 18 19/* 20 * Special internal param type to indicate the end of an allocate OSSL_PARAM 21 * array. 22 */ 23 24typedef struct { 25 const char *key; 26 int type; 27 int secure; 28 size_t size; 29 size_t alloc_blocks; 30 const BIGNUM *bn; 31 const void *string; 32 union { 33 /* 34 * These fields are never directly addressed, but their sizes are 35 * imporant so that all native types can be copied here without overrun. 36 */ 37 ossl_intmax_t i; 38 ossl_uintmax_t u; 39 double d; 40 } num; 41} OSSL_PARAM_BLD_DEF; 42 43DEFINE_STACK_OF(OSSL_PARAM_BLD_DEF) 44 45struct ossl_param_bld_st { 46 size_t total_blocks; 47 size_t secure_blocks; 48 STACK_OF(OSSL_PARAM_BLD_DEF) *params; 49}; 50 51static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key, 52 int size, size_t alloc, int type, 53 int secure) 54{ 55 OSSL_PARAM_BLD_DEF *pd = OPENSSL_zalloc(sizeof(*pd)); 56 57 if (pd == NULL) { 58 ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 59 return NULL; 60 } 61 pd->key = key; 62 pd->type = type; 63 pd->size = size; 64 pd->alloc_blocks = ossl_param_bytes_to_blocks(alloc); 65 if ((pd->secure = secure) != 0) 66 bld->secure_blocks += pd->alloc_blocks; 67 else 68 bld->total_blocks += pd->alloc_blocks; 69 if (sk_OSSL_PARAM_BLD_DEF_push(bld->params, pd) <= 0) { 70 OPENSSL_free(pd); 71 pd = NULL; 72 } 73 return pd; 74} 75 76static int param_push_num(OSSL_PARAM_BLD *bld, const char *key, 77 void *num, size_t size, int type) 78{ 79 OSSL_PARAM_BLD_DEF *pd = param_push(bld, key, size, size, type, 0); 80 81 if (pd == NULL) 82 return 0; 83 if (size > sizeof(pd->num)) { 84 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_BYTES); 85 return 0; 86 } 87 memcpy(&pd->num, num, size); 88 return 1; 89} 90 91OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void) 92{ 93 OSSL_PARAM_BLD *r = OPENSSL_zalloc(sizeof(OSSL_PARAM_BLD)); 94 95 if (r != NULL) { 96 r->params = sk_OSSL_PARAM_BLD_DEF_new_null(); 97 if (r->params == NULL) { 98 OPENSSL_free(r); 99 r = NULL; 100 } 101 } 102 return r; 103} 104 105static void free_all_params(OSSL_PARAM_BLD *bld) 106{ 107 int i, n = sk_OSSL_PARAM_BLD_DEF_num(bld->params); 108 109 for (i = 0; i < n; i++) 110 OPENSSL_free(sk_OSSL_PARAM_BLD_DEF_pop(bld->params)); 111} 112 113void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld) 114{ 115 if (bld == NULL) 116 return; 117 free_all_params(bld); 118 sk_OSSL_PARAM_BLD_DEF_free(bld->params); 119 OPENSSL_free(bld); 120} 121 122int OSSL_PARAM_BLD_push_int(OSSL_PARAM_BLD *bld, const char *key, int num) 123{ 124 return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER); 125} 126 127int OSSL_PARAM_BLD_push_uint(OSSL_PARAM_BLD *bld, const char *key, 128 unsigned int num) 129{ 130 return param_push_num(bld, key, &num, sizeof(num), 131 OSSL_PARAM_UNSIGNED_INTEGER); 132} 133 134int OSSL_PARAM_BLD_push_long(OSSL_PARAM_BLD *bld, const char *key, 135 long int num) 136{ 137 return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER); 138} 139 140int OSSL_PARAM_BLD_push_ulong(OSSL_PARAM_BLD *bld, const char *key, 141 unsigned long int num) 142{ 143 return param_push_num(bld, key, &num, sizeof(num), 144 OSSL_PARAM_UNSIGNED_INTEGER); 145} 146 147int OSSL_PARAM_BLD_push_int32(OSSL_PARAM_BLD *bld, const char *key, 148 int32_t num) 149{ 150 return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER); 151} 152 153int OSSL_PARAM_BLD_push_uint32(OSSL_PARAM_BLD *bld, const char *key, 154 uint32_t num) 155{ 156 return param_push_num(bld, key, &num, sizeof(num), 157 OSSL_PARAM_UNSIGNED_INTEGER); 158} 159 160int OSSL_PARAM_BLD_push_int64(OSSL_PARAM_BLD *bld, const char *key, 161 int64_t num) 162{ 163 return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER); 164} 165 166int OSSL_PARAM_BLD_push_uint64(OSSL_PARAM_BLD *bld, const char *key, 167 uint64_t num) 168{ 169 return param_push_num(bld, key, &num, sizeof(num), 170 OSSL_PARAM_UNSIGNED_INTEGER); 171} 172 173int OSSL_PARAM_BLD_push_size_t(OSSL_PARAM_BLD *bld, const char *key, 174 size_t num) 175{ 176 return param_push_num(bld, key, &num, sizeof(num), 177 OSSL_PARAM_UNSIGNED_INTEGER); 178} 179 180int OSSL_PARAM_BLD_push_time_t(OSSL_PARAM_BLD *bld, const char *key, 181 time_t num) 182{ 183 return param_push_num(bld, key, &num, sizeof(num), 184 OSSL_PARAM_INTEGER); 185} 186 187int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD *bld, const char *key, 188 double num) 189{ 190 return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_REAL); 191} 192 193int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key, 194 const BIGNUM *bn) 195{ 196 return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn, 197 bn == NULL ? 0 : BN_num_bytes(bn)); 198} 199 200int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, 201 const BIGNUM *bn, size_t sz) 202{ 203 int n, secure = 0; 204 OSSL_PARAM_BLD_DEF *pd; 205 206 if (bn != NULL) { 207 if (BN_is_negative(bn)) { 208 ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_UNSUPPORTED, 209 "Negative big numbers are unsupported for OSSL_PARAM"); 210 return 0; 211 } 212 213 n = BN_num_bytes(bn); 214 if (n < 0) { 215 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_ZERO_LENGTH_NUMBER); 216 return 0; 217 } 218 if (sz < (size_t)n) { 219 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER); 220 return 0; 221 } 222 if (BN_get_flags(bn, BN_FLG_SECURE) == BN_FLG_SECURE) 223 secure = 1; 224 225 /* The BIGNUM is zero, we must transfer at least one byte */ 226 if (sz == 0) 227 sz++; 228 } 229 pd = param_push(bld, key, sz, sz, OSSL_PARAM_UNSIGNED_INTEGER, secure); 230 if (pd == NULL) 231 return 0; 232 pd->bn = bn; 233 return 1; 234} 235 236int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, 237 const char *buf, size_t bsize) 238{ 239 OSSL_PARAM_BLD_DEF *pd; 240 int secure; 241 242 if (bsize == 0) 243 bsize = strlen(buf); 244 if (bsize > INT_MAX) { 245 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG); 246 return 0; 247 } 248 secure = CRYPTO_secure_allocated(buf); 249 pd = param_push(bld, key, bsize, bsize + 1, OSSL_PARAM_UTF8_STRING, secure); 250 if (pd == NULL) 251 return 0; 252 pd->string = buf; 253 return 1; 254} 255 256int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, 257 char *buf, size_t bsize) 258{ 259 OSSL_PARAM_BLD_DEF *pd; 260 261 if (bsize == 0) 262 bsize = strlen(buf); 263 if (bsize > INT_MAX) { 264 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG); 265 return 0; 266 } 267 pd = param_push(bld, key, bsize, sizeof(buf), OSSL_PARAM_UTF8_PTR, 0); 268 if (pd == NULL) 269 return 0; 270 pd->string = buf; 271 return 1; 272} 273 274int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, 275 const void *buf, size_t bsize) 276{ 277 OSSL_PARAM_BLD_DEF *pd; 278 int secure; 279 280 if (bsize > INT_MAX) { 281 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG); 282 return 0; 283 } 284 secure = CRYPTO_secure_allocated(buf); 285 pd = param_push(bld, key, bsize, bsize, OSSL_PARAM_OCTET_STRING, secure); 286 if (pd == NULL) 287 return 0; 288 pd->string = buf; 289 return 1; 290} 291 292int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key, 293 void *buf, size_t bsize) 294{ 295 OSSL_PARAM_BLD_DEF *pd; 296 297 if (bsize > INT_MAX) { 298 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG); 299 return 0; 300 } 301 pd = param_push(bld, key, bsize, sizeof(buf), OSSL_PARAM_OCTET_PTR, 0); 302 if (pd == NULL) 303 return 0; 304 pd->string = buf; 305 return 1; 306} 307 308static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param, 309 OSSL_PARAM_ALIGNED_BLOCK *blk, 310 OSSL_PARAM_ALIGNED_BLOCK *secure) 311{ 312 int i, num = sk_OSSL_PARAM_BLD_DEF_num(bld->params); 313 OSSL_PARAM_BLD_DEF *pd; 314 void *p; 315 316 for (i = 0; i < num; i++) { 317 pd = sk_OSSL_PARAM_BLD_DEF_value(bld->params, i); 318 param[i].key = pd->key; 319 param[i].data_type = pd->type; 320 param[i].data_size = pd->size; 321 param[i].return_size = OSSL_PARAM_UNMODIFIED; 322 323 if (pd->secure) { 324 p = secure; 325 secure += pd->alloc_blocks; 326 } else { 327 p = blk; 328 blk += pd->alloc_blocks; 329 } 330 param[i].data = p; 331 if (pd->bn != NULL) { 332 /* BIGNUM */ 333 BN_bn2nativepad(pd->bn, (unsigned char *)p, pd->size); 334 } else if (pd->type == OSSL_PARAM_OCTET_PTR 335 || pd->type == OSSL_PARAM_UTF8_PTR) { 336 /* PTR */ 337 *(const void **)p = pd->string; 338 } else if (pd->type == OSSL_PARAM_OCTET_STRING 339 || pd->type == OSSL_PARAM_UTF8_STRING) { 340 if (pd->string != NULL) 341 memcpy(p, pd->string, pd->size); 342 else 343 memset(p, 0, pd->size); 344 if (pd->type == OSSL_PARAM_UTF8_STRING) 345 ((char *)p)[pd->size] = '\0'; 346 } else { 347 /* Number, but could also be a NULL BIGNUM */ 348 if (pd->size > sizeof(pd->num)) 349 memset(p, 0, pd->size); 350 else if (pd->size > 0) 351 memcpy(p, &pd->num, pd->size); 352 } 353 } 354 param[i] = OSSL_PARAM_construct_end(); 355 return param + i; 356} 357 358OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld) 359{ 360 OSSL_PARAM_ALIGNED_BLOCK *blk, *s = NULL; 361 OSSL_PARAM *params, *last; 362 const int num = sk_OSSL_PARAM_BLD_DEF_num(bld->params); 363 const size_t p_blks = ossl_param_bytes_to_blocks((1 + num) * sizeof(*params)); 364 const size_t total = OSSL_PARAM_ALIGN_SIZE * (p_blks + bld->total_blocks); 365 const size_t ss = OSSL_PARAM_ALIGN_SIZE * bld->secure_blocks; 366 367 if (ss > 0) { 368 s = OPENSSL_secure_malloc(ss); 369 if (s == NULL) { 370 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_SECURE_MALLOC_FAILURE); 371 return NULL; 372 } 373 } 374 params = OPENSSL_malloc(total); 375 if (params == NULL) { 376 ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 377 OPENSSL_secure_free(s); 378 return NULL; 379 } 380 blk = p_blks + (OSSL_PARAM_ALIGNED_BLOCK *)(params); 381 last = param_bld_convert(bld, params, blk, s); 382 ossl_param_set_secure_block(last, s, ss); 383 384 /* Reset builder for reuse */ 385 bld->total_blocks = 0; 386 bld->secure_blocks = 0; 387 free_all_params(bld); 388 return params; 389} 390