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/params.h> 13#include "internal/thread_once.h" 14#include "internal/numbers.h" 15#include "internal/endian.h" 16 17/* 18 * Return the number of bits in the mantissa of a double. This is used to 19 * shift a larger integral value to determine if it will exactly fit into a 20 * double. 21 */ 22static unsigned int real_shift(void) 23{ 24 return sizeof(double) == 4 ? 24 : 53; 25} 26 27OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *p, const char *key) 28{ 29 if (p != NULL && key != NULL) 30 for (; p->key != NULL; p++) 31 if (strcmp(key, p->key) == 0) 32 return p; 33 return NULL; 34} 35 36const OSSL_PARAM *OSSL_PARAM_locate_const(const OSSL_PARAM *p, const char *key) 37{ 38 return OSSL_PARAM_locate((OSSL_PARAM *)p, key); 39} 40 41static OSSL_PARAM ossl_param_construct(const char *key, unsigned int data_type, 42 void *data, size_t data_size) 43{ 44 OSSL_PARAM res; 45 46 res.key = key; 47 res.data_type = data_type; 48 res.data = data; 49 res.data_size = data_size; 50 res.return_size = OSSL_PARAM_UNMODIFIED; 51 return res; 52} 53 54int OSSL_PARAM_modified(const OSSL_PARAM *p) 55{ 56 return p != NULL && p->return_size != OSSL_PARAM_UNMODIFIED; 57} 58 59void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *p) 60{ 61 if (p != NULL) 62 while (p->key != NULL) 63 p++->return_size = OSSL_PARAM_UNMODIFIED; 64} 65 66/* Return non-zero if the signed number is negative */ 67static int is_negative(const void *number, size_t s) 68{ 69 const unsigned char *n = number; 70 DECLARE_IS_ENDIAN; 71 72 return 0x80 & (IS_BIG_ENDIAN ? n[0] : n[s - 1]); 73} 74 75/* Check that all the bytes specified match the expected sign byte */ 76static int check_sign_bytes(const unsigned char *p, size_t n, unsigned char s) 77{ 78 size_t i; 79 80 for (i = 0; i < n; i++) 81 if (p[i] != s) 82 return 0; 83 return 1; 84} 85 86/* 87 * Copy an integer to another integer. 88 * Handle different length integers and signed and unsigned integers. 89 * Both integers are in native byte ordering. 90 */ 91static int copy_integer(unsigned char *dest, size_t dest_len, 92 const unsigned char *src, size_t src_len, 93 unsigned char pad, int signed_int) 94{ 95 size_t n; 96 DECLARE_IS_ENDIAN; 97 98 if (IS_BIG_ENDIAN) { 99 if (src_len < dest_len) { 100 n = dest_len - src_len; 101 memset(dest, pad, n); 102 memcpy(dest + n, src, src_len); 103 } else { 104 n = src_len - dest_len; 105 if (!check_sign_bytes(src, n, pad) 106 /* 107 * Shortening a signed value must retain the correct sign. 108 * Avoiding this kind of thing: -253 = 0xff03 -> 0x03 = 3 109 */ 110 || (signed_int && ((pad ^ src[n]) & 0x80) != 0)) 111 return 0; 112 memcpy(dest, src + n, dest_len); 113 } 114 } else /* IS_LITTLE_ENDIAN */ { 115 if (src_len < dest_len) { 116 n = dest_len - src_len; 117 memset(dest + src_len, pad, n); 118 memcpy(dest, src, src_len); 119 } else { 120 n = src_len - dest_len; 121 if (!check_sign_bytes(src + dest_len, n, pad) 122 /* 123 * Shortening a signed value must retain the correct sign. 124 * Avoiding this kind of thing: 130 = 0x0082 -> 0x82 = -126 125 */ 126 || (signed_int && ((pad ^ src[dest_len - 1]) & 0x80) != 0)) 127 return 0; 128 memcpy(dest, src, dest_len); 129 } 130 } 131 return 1; 132} 133 134/* Copy a signed number to a signed number of possibly different length */ 135static int signed_from_signed(void *dest, size_t dest_len, 136 const void *src, size_t src_len) 137{ 138 return copy_integer(dest, dest_len, src, src_len, 139 is_negative(src, src_len) ? 0xff : 0, 1); 140} 141 142/* Copy an unsigned number to a signed number of possibly different length */ 143static int signed_from_unsigned(void *dest, size_t dest_len, 144 const void *src, size_t src_len) 145{ 146 return copy_integer(dest, dest_len, src, src_len, 0, 1); 147} 148 149/* Copy a signed number to an unsigned number of possibly different length */ 150static int unsigned_from_signed(void *dest, size_t dest_len, 151 const void *src, size_t src_len) 152{ 153 if (is_negative(src, src_len)) 154 return 0; 155 return copy_integer(dest, dest_len, src, src_len, 0, 0); 156} 157 158/* Copy an unsigned number to an unsigned number of possibly different length */ 159static int unsigned_from_unsigned(void *dest, size_t dest_len, 160 const void *src, size_t src_len) 161{ 162 return copy_integer(dest, dest_len, src, src_len, 0, 0); 163} 164 165/* General purpose get integer parameter call that handles odd sizes */ 166static int general_get_int(const OSSL_PARAM *p, void *val, size_t val_size) 167{ 168 if (p->data_type == OSSL_PARAM_INTEGER) 169 return signed_from_signed(val, val_size, p->data, p->data_size); 170 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) 171 return signed_from_unsigned(val, val_size, p->data, p->data_size); 172 return 0; 173} 174 175/* General purpose set integer parameter call that handles odd sizes */ 176static int general_set_int(OSSL_PARAM *p, void *val, size_t val_size) 177{ 178 int r = 0; 179 180 p->return_size = val_size; /* Expected size */ 181 if (p->data == NULL) 182 return 1; 183 if (p->data_type == OSSL_PARAM_INTEGER) 184 r = signed_from_signed(p->data, p->data_size, val, val_size); 185 else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) 186 r = unsigned_from_signed(p->data, p->data_size, val, val_size); 187 p->return_size = r ? p->data_size : val_size; 188 return r; 189} 190 191/* General purpose get unsigned integer parameter call that handles odd sizes */ 192static int general_get_uint(const OSSL_PARAM *p, void *val, size_t val_size) 193{ 194 if (p->data_type == OSSL_PARAM_INTEGER) 195 return unsigned_from_signed(val, val_size, p->data, p->data_size); 196 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) 197 return unsigned_from_unsigned(val, val_size, p->data, p->data_size); 198 return 0; 199} 200 201/* General purpose set unsigned integer parameter call that handles odd sizes */ 202static int general_set_uint(OSSL_PARAM *p, void *val, size_t val_size) 203{ 204 int r = 0; 205 206 p->return_size = val_size; /* Expected size */ 207 if (p->data == NULL) 208 return 1; 209 if (p->data_type == OSSL_PARAM_INTEGER) 210 r = signed_from_unsigned(p->data, p->data_size, val, val_size); 211 else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) 212 r = unsigned_from_unsigned(p->data, p->data_size, val, val_size); 213 p->return_size = r ? p->data_size : val_size; 214 return r; 215} 216 217int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val) 218{ 219#ifndef OPENSSL_SMALL_FOOTPRINT 220 switch (sizeof(int)) { 221 case sizeof(int32_t): 222 return OSSL_PARAM_get_int32(p, (int32_t *)val); 223 case sizeof(int64_t): 224 return OSSL_PARAM_get_int64(p, (int64_t *)val); 225 } 226#endif 227 return general_get_int(p, val, sizeof(*val)); 228} 229 230int OSSL_PARAM_set_int(OSSL_PARAM *p, int val) 231{ 232#ifndef OPENSSL_SMALL_FOOTPRINT 233 switch (sizeof(int)) { 234 case sizeof(int32_t): 235 return OSSL_PARAM_set_int32(p, (int32_t)val); 236 case sizeof(int64_t): 237 return OSSL_PARAM_set_int64(p, (int64_t)val); 238 } 239#endif 240 return general_set_int(p, &val, sizeof(val)); 241} 242 243OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf) 244{ 245 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int)); 246} 247 248int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val) 249{ 250#ifndef OPENSSL_SMALL_FOOTPRINT 251 switch (sizeof(unsigned int)) { 252 case sizeof(uint32_t): 253 return OSSL_PARAM_get_uint32(p, (uint32_t *)val); 254 case sizeof(uint64_t): 255 return OSSL_PARAM_get_uint64(p, (uint64_t *)val); 256 } 257#endif 258 return general_get_uint(p, val, sizeof(*val)); 259} 260 261int OSSL_PARAM_set_uint(OSSL_PARAM *p, unsigned int val) 262{ 263#ifndef OPENSSL_SMALL_FOOTPRINT 264 switch (sizeof(unsigned int)) { 265 case sizeof(uint32_t): 266 return OSSL_PARAM_set_uint32(p, (uint32_t)val); 267 case sizeof(uint64_t): 268 return OSSL_PARAM_set_uint64(p, (uint64_t)val); 269 } 270#endif 271 return general_set_uint(p, &val, sizeof(val)); 272} 273 274OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf) 275{ 276 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf, 277 sizeof(unsigned int)); 278} 279 280int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val) 281{ 282#ifndef OPENSSL_SMALL_FOOTPRINT 283 switch (sizeof(long int)) { 284 case sizeof(int32_t): 285 return OSSL_PARAM_get_int32(p, (int32_t *)val); 286 case sizeof(int64_t): 287 return OSSL_PARAM_get_int64(p, (int64_t *)val); 288 } 289#endif 290 return general_get_int(p, val, sizeof(*val)); 291} 292 293int OSSL_PARAM_set_long(OSSL_PARAM *p, long int val) 294{ 295#ifndef OPENSSL_SMALL_FOOTPRINT 296 switch (sizeof(long int)) { 297 case sizeof(int32_t): 298 return OSSL_PARAM_set_int32(p, (int32_t)val); 299 case sizeof(int64_t): 300 return OSSL_PARAM_set_int64(p, (int64_t)val); 301 } 302#endif 303 return general_set_int(p, &val, sizeof(val)); 304} 305 306OSSL_PARAM OSSL_PARAM_construct_long(const char *key, long int *buf) 307{ 308 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(long int)); 309} 310 311int OSSL_PARAM_get_ulong(const OSSL_PARAM *p, unsigned long int *val) 312{ 313#ifndef OPENSSL_SMALL_FOOTPRINT 314 switch (sizeof(unsigned long int)) { 315 case sizeof(uint32_t): 316 return OSSL_PARAM_get_uint32(p, (uint32_t *)val); 317 case sizeof(uint64_t): 318 return OSSL_PARAM_get_uint64(p, (uint64_t *)val); 319 } 320#endif 321 return general_get_uint(p, val, sizeof(*val)); 322} 323 324int OSSL_PARAM_set_ulong(OSSL_PARAM *p, unsigned long int val) 325{ 326#ifndef OPENSSL_SMALL_FOOTPRINT 327 switch (sizeof(unsigned long int)) { 328 case sizeof(uint32_t): 329 return OSSL_PARAM_set_uint32(p, (uint32_t)val); 330 case sizeof(uint64_t): 331 return OSSL_PARAM_set_uint64(p, (uint64_t)val); 332 } 333#endif 334 return general_set_uint(p, &val, sizeof(val)); 335} 336 337OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf) 338{ 339 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf, 340 sizeof(unsigned long int)); 341} 342 343int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val) 344{ 345 double d; 346 347 if (val == NULL || p == NULL ) 348 return 0; 349 350 if (p->data_type == OSSL_PARAM_INTEGER) { 351#ifndef OPENSSL_SMALL_FOOTPRINT 352 int64_t i64; 353 354 switch (p->data_size) { 355 case sizeof(int32_t): 356 *val = *(const int32_t *)p->data; 357 return 1; 358 case sizeof(int64_t): 359 i64 = *(const int64_t *)p->data; 360 if (i64 >= INT32_MIN && i64 <= INT32_MAX) { 361 *val = (int32_t)i64; 362 return 1; 363 } 364 return 0; 365 } 366#endif 367 return general_get_int(p, val, sizeof(*val)); 368 369 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { 370#ifndef OPENSSL_SMALL_FOOTPRINT 371 uint32_t u32; 372 uint64_t u64; 373 374 switch (p->data_size) { 375 case sizeof(uint32_t): 376 u32 = *(const uint32_t *)p->data; 377 if (u32 <= INT32_MAX) { 378 *val = (int32_t)u32; 379 return 1; 380 } 381 return 0; 382 case sizeof(uint64_t): 383 u64 = *(const uint64_t *)p->data; 384 if (u64 <= INT32_MAX) { 385 *val = (int32_t)u64; 386 return 1; 387 } 388 return 0; 389 } 390#endif 391 return general_get_int(p, val, sizeof(*val)); 392 393 } else if (p->data_type == OSSL_PARAM_REAL) { 394 switch (p->data_size) { 395 case sizeof(double): 396 d = *(const double *)p->data; 397 if (d >= INT32_MIN && d <= INT32_MAX && d == (int32_t)d) { 398 *val = (int32_t)d; 399 return 1; 400 } 401 break; 402 } 403 } 404 return 0; 405} 406 407int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val) 408{ 409 if (p == NULL) 410 return 0; 411 p->return_size = 0; 412 if (p->data_type == OSSL_PARAM_INTEGER) { 413#ifndef OPENSSL_SMALL_FOOTPRINT 414 p->return_size = sizeof(int32_t); /* Minimum expected size */ 415 if (p->data == NULL) 416 return 1; 417 switch (p->data_size) { 418 case sizeof(int32_t): 419 *(int32_t *)p->data = val; 420 return 1; 421 case sizeof(int64_t): 422 p->return_size = sizeof(int64_t); 423 *(int64_t *)p->data = (int64_t)val; 424 return 1; 425 } 426#endif 427 return general_set_int(p, &val, sizeof(val)); 428 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) { 429#ifndef OPENSSL_SMALL_FOOTPRINT 430 p->return_size = sizeof(uint32_t); /* Minimum expected size */ 431 if (p->data == NULL) 432 return 1; 433 switch (p->data_size) { 434 case sizeof(uint32_t): 435 *(uint32_t *)p->data = (uint32_t)val; 436 return 1; 437 case sizeof(uint64_t): 438 p->return_size = sizeof(uint64_t); 439 *(uint64_t *)p->data = (uint64_t)val; 440 return 1; 441 } 442#endif 443 return general_set_int(p, &val, sizeof(val)); 444 } else if (p->data_type == OSSL_PARAM_REAL) { 445 p->return_size = sizeof(double); 446 if (p->data == NULL) 447 return 1; 448 switch (p->data_size) { 449 case sizeof(double): 450 *(double *)p->data = (double)val; 451 return 1; 452 } 453 } 454 return 0; 455} 456 457OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf) 458{ 459 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, 460 sizeof(int32_t)); 461} 462 463int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val) 464{ 465 double d; 466 467 if (val == NULL || p == NULL) 468 return 0; 469 470 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { 471#ifndef OPENSSL_SMALL_FOOTPRINT 472 uint64_t u64; 473 474 switch (p->data_size) { 475 case sizeof(uint32_t): 476 *val = *(const uint32_t *)p->data; 477 return 1; 478 case sizeof(uint64_t): 479 u64 = *(const uint64_t *)p->data; 480 if (u64 <= UINT32_MAX) { 481 *val = (uint32_t)u64; 482 return 1; 483 } 484 return 0; 485 } 486#endif 487 return general_get_uint(p, val, sizeof(*val)); 488 } else if (p->data_type == OSSL_PARAM_INTEGER) { 489#ifndef OPENSSL_SMALL_FOOTPRINT 490 int32_t i32; 491 int64_t i64; 492 493 switch (p->data_size) { 494 case sizeof(int32_t): 495 i32 = *(const int32_t *)p->data; 496 if (i32 >= 0) { 497 *val = i32; 498 return 1; 499 } 500 return 0; 501 case sizeof(int64_t): 502 i64 = *(const int64_t *)p->data; 503 if (i64 >= 0 && i64 <= UINT32_MAX) { 504 *val = (uint32_t)i64; 505 return 1; 506 } 507 return 0; 508 } 509#endif 510 return general_get_uint(p, val, sizeof(*val)); 511 } else if (p->data_type == OSSL_PARAM_REAL) { 512 switch (p->data_size) { 513 case sizeof(double): 514 d = *(const double *)p->data; 515 if (d >= 0 && d <= UINT32_MAX && d == (uint32_t)d) { 516 *val = (uint32_t)d; 517 return 1; 518 } 519 break; 520 } 521 } 522 return 0; 523} 524 525int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val) 526{ 527 if (p == NULL) 528 return 0; 529 p->return_size = 0; 530 531 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { 532#ifndef OPENSSL_SMALL_FOOTPRINT 533 p->return_size = sizeof(uint32_t); /* Minimum expected size */ 534 if (p->data == NULL) 535 return 1; 536 switch (p->data_size) { 537 case sizeof(uint32_t): 538 *(uint32_t *)p->data = val; 539 return 1; 540 case sizeof(uint64_t): 541 p->return_size = sizeof(uint64_t); 542 *(uint64_t *)p->data = val; 543 return 1; 544 } 545#endif 546 return general_set_uint(p, &val, sizeof(val)); 547 } else if (p->data_type == OSSL_PARAM_INTEGER) { 548#ifndef OPENSSL_SMALL_FOOTPRINT 549 p->return_size = sizeof(int32_t); /* Minimum expected size */ 550 if (p->data == NULL) 551 return 1; 552 switch (p->data_size) { 553 case sizeof(int32_t): 554 if (val <= INT32_MAX) { 555 *(int32_t *)p->data = (int32_t)val; 556 return 1; 557 } 558 return 0; 559 case sizeof(int64_t): 560 p->return_size = sizeof(int64_t); 561 *(int64_t *)p->data = (int64_t)val; 562 return 1; 563 } 564#endif 565 return general_set_uint(p, &val, sizeof(val)); 566 } else if (p->data_type == OSSL_PARAM_REAL) { 567 p->return_size = sizeof(double); 568 if (p->data == NULL) 569 return 1; 570 switch (p->data_size) { 571 case sizeof(double): 572 *(double *)p->data = (double)val; 573 return 1; 574 } 575 } 576 return 0; 577} 578 579OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf) 580{ 581 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf, 582 sizeof(uint32_t)); 583} 584 585int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val) 586{ 587 double d; 588 589 if (val == NULL || p == NULL ) 590 return 0; 591 592 if (p->data_type == OSSL_PARAM_INTEGER) { 593#ifndef OPENSSL_SMALL_FOOTPRINT 594 switch (p->data_size) { 595 case sizeof(int32_t): 596 *val = *(const int32_t *)p->data; 597 return 1; 598 case sizeof(int64_t): 599 *val = *(const int64_t *)p->data; 600 return 1; 601 } 602#endif 603 return general_get_int(p, val, sizeof(*val)); 604 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { 605#ifndef OPENSSL_SMALL_FOOTPRINT 606 uint64_t u64; 607 608 switch (p->data_size) { 609 case sizeof(uint32_t): 610 *val = *(const uint32_t *)p->data; 611 return 1; 612 case sizeof(uint64_t): 613 u64 = *(const uint64_t *)p->data; 614 if (u64 <= INT64_MAX) { 615 *val = (int64_t)u64; 616 return 1; 617 } 618 return 0; 619 } 620#endif 621 return general_get_int(p, val, sizeof(*val)); 622 } else if (p->data_type == OSSL_PARAM_REAL) { 623 switch (p->data_size) { 624 case sizeof(double): 625 d = *(const double *)p->data; 626 if (d >= INT64_MIN 627 /* 628 * By subtracting 65535 (2^16-1) we cancel the low order 629 * 15 bits of INT64_MAX to avoid using imprecise floating 630 * point values. 631 */ 632 && d < (double)(INT64_MAX - 65535) + 65536.0 633 && d == (int64_t)d) { 634 *val = (int64_t)d; 635 return 1; 636 } 637 break; 638 } 639 } 640 return 0; 641} 642 643int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val) 644{ 645 uint64_t u64; 646 647 if (p == NULL) 648 return 0; 649 p->return_size = 0; 650 if (p->data_type == OSSL_PARAM_INTEGER) { 651#ifndef OPENSSL_SMALL_FOOTPRINT 652 p->return_size = sizeof(int64_t); /* Expected size */ 653 if (p->data == NULL) 654 return 1; 655 switch (p->data_size) { 656 case sizeof(int32_t): 657 if (val >= INT32_MIN && val <= INT32_MAX) { 658 p->return_size = sizeof(int32_t); 659 *(int32_t *)p->data = (int32_t)val; 660 return 1; 661 } 662 return 0; 663 case sizeof(int64_t): 664 *(int64_t *)p->data = val; 665 return 1; 666 } 667#endif 668 return general_set_int(p, &val, sizeof(val)); 669 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) { 670#ifndef OPENSSL_SMALL_FOOTPRINT 671 p->return_size = sizeof(uint64_t); /* Expected size */ 672 if (p->data == NULL) 673 return 1; 674 switch (p->data_size) { 675 case sizeof(uint32_t): 676 if (val <= UINT32_MAX) { 677 p->return_size = sizeof(uint32_t); 678 *(uint32_t *)p->data = (uint32_t)val; 679 return 1; 680 } 681 return 0; 682 case sizeof(uint64_t): 683 *(uint64_t *)p->data = (uint64_t)val; 684 return 1; 685 } 686#endif 687 return general_set_int(p, &val, sizeof(val)); 688 } else if (p->data_type == OSSL_PARAM_REAL) { 689 p->return_size = sizeof(double); 690 if (p->data == NULL) 691 return 1; 692 switch (p->data_size) { 693 case sizeof(double): 694 u64 = val < 0 ? -val : val; 695 if ((u64 >> real_shift()) == 0) { 696 *(double *)p->data = (double)val; 697 return 1; 698 } 699 break; 700 } 701 } 702 return 0; 703} 704 705OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf) 706{ 707 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int64_t)); 708} 709 710int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val) 711{ 712 double d; 713 714 if (val == NULL || p == NULL) 715 return 0; 716 717 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { 718#ifndef OPENSSL_SMALL_FOOTPRINT 719 switch (p->data_size) { 720 case sizeof(uint32_t): 721 *val = *(const uint32_t *)p->data; 722 return 1; 723 case sizeof(uint64_t): 724 *val = *(const uint64_t *)p->data; 725 return 1; 726 } 727#endif 728 return general_get_uint(p, val, sizeof(*val)); 729 } else if (p->data_type == OSSL_PARAM_INTEGER) { 730#ifndef OPENSSL_SMALL_FOOTPRINT 731 int32_t i32; 732 int64_t i64; 733 734 switch (p->data_size) { 735 case sizeof(int32_t): 736 i32 = *(const int32_t *)p->data; 737 if (i32 >= 0) { 738 *val = (uint64_t)i32; 739 return 1; 740 } 741 return 0; 742 case sizeof(int64_t): 743 i64 = *(const int64_t *)p->data; 744 if (i64 >= 0) { 745 *val = (uint64_t)i64; 746 return 1; 747 } 748 return 0; 749 } 750#endif 751 return general_get_uint(p, val, sizeof(*val)); 752 } else if (p->data_type == OSSL_PARAM_REAL) { 753 switch (p->data_size) { 754 case sizeof(double): 755 d = *(const double *)p->data; 756 if (d >= 0 757 /* 758 * By subtracting 65535 (2^16-1) we cancel the low order 759 * 15 bits of UINT64_MAX to avoid using imprecise floating 760 * point values. 761 */ 762 && d < (double)(UINT64_MAX - 65535) + 65536.0 763 && d == (uint64_t)d) { 764 *val = (uint64_t)d; 765 return 1; 766 } 767 break; 768 } 769 } 770 return 0; 771} 772 773int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val) 774{ 775 if (p == NULL) 776 return 0; 777 p->return_size = 0; 778 779 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { 780#ifndef OPENSSL_SMALL_FOOTPRINT 781 p->return_size = sizeof(uint64_t); /* Expected size */ 782 if (p->data == NULL) 783 return 1; 784 switch (p->data_size) { 785 case sizeof(uint32_t): 786 if (val <= UINT32_MAX) { 787 p->return_size = sizeof(uint32_t); 788 *(uint32_t *)p->data = (uint32_t)val; 789 return 1; 790 } 791 return 0; 792 case sizeof(uint64_t): 793 *(uint64_t *)p->data = val; 794 return 1; 795 } 796#endif 797 return general_set_uint(p, &val, sizeof(val)); 798 } else if (p->data_type == OSSL_PARAM_INTEGER) { 799#ifndef OPENSSL_SMALL_FOOTPRINT 800 p->return_size = sizeof(int64_t); /* Expected size */ 801 if (p->data == NULL) 802 return 1; 803 switch (p->data_size) { 804 case sizeof(int32_t): 805 if (val <= INT32_MAX) { 806 p->return_size = sizeof(int32_t); 807 *(int32_t *)p->data = (int32_t)val; 808 return 1; 809 } 810 return 0; 811 case sizeof(int64_t): 812 if (val <= INT64_MAX) { 813 *(int64_t *)p->data = (int64_t)val; 814 return 1; 815 } 816 return 0; 817 } 818#endif 819 return general_set_uint(p, &val, sizeof(val)); 820 } else if (p->data_type == OSSL_PARAM_REAL) { 821 p->return_size = sizeof(double); 822 switch (p->data_size) { 823 case sizeof(double): 824 if ((val >> real_shift()) == 0) { 825 *(double *)p->data = (double)val; 826 return 1; 827 } 828 break; 829 } 830 } 831 return 0; 832} 833 834OSSL_PARAM OSSL_PARAM_construct_uint64(const char *key, uint64_t *buf) 835{ 836 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf, 837 sizeof(uint64_t)); 838} 839 840int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val) 841{ 842#ifndef OPENSSL_SMALL_FOOTPRINT 843 switch (sizeof(size_t)) { 844 case sizeof(uint32_t): 845 return OSSL_PARAM_get_uint32(p, (uint32_t *)val); 846 case sizeof(uint64_t): 847 return OSSL_PARAM_get_uint64(p, (uint64_t *)val); 848 } 849#endif 850 return general_get_uint(p, val, sizeof(*val)); 851} 852 853int OSSL_PARAM_set_size_t(OSSL_PARAM *p, size_t val) 854{ 855#ifndef OPENSSL_SMALL_FOOTPRINT 856 switch (sizeof(size_t)) { 857 case sizeof(uint32_t): 858 return OSSL_PARAM_set_uint32(p, (uint32_t)val); 859 case sizeof(uint64_t): 860 return OSSL_PARAM_set_uint64(p, (uint64_t)val); 861 } 862#endif 863 return general_set_uint(p, &val, sizeof(val)); 864} 865 866OSSL_PARAM OSSL_PARAM_construct_size_t(const char *key, size_t *buf) 867{ 868 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf, 869 sizeof(size_t)); 870} 871 872int OSSL_PARAM_get_time_t(const OSSL_PARAM *p, time_t *val) 873{ 874#ifndef OPENSSL_SMALL_FOOTPRINT 875 switch (sizeof(time_t)) { 876 case sizeof(int32_t): 877 return OSSL_PARAM_get_int32(p, (int32_t *)val); 878 case sizeof(int64_t): 879 return OSSL_PARAM_get_int64(p, (int64_t *)val); 880 } 881#endif 882 return general_get_int(p, val, sizeof(*val)); 883} 884 885int OSSL_PARAM_set_time_t(OSSL_PARAM *p, time_t val) 886{ 887#ifndef OPENSSL_SMALL_FOOTPRINT 888 switch (sizeof(time_t)) { 889 case sizeof(int32_t): 890 return OSSL_PARAM_set_int32(p, (int32_t)val); 891 case sizeof(int64_t): 892 return OSSL_PARAM_set_int64(p, (int64_t)val); 893 } 894#endif 895 return general_set_int(p, &val, sizeof(val)); 896} 897 898OSSL_PARAM OSSL_PARAM_construct_time_t(const char *key, time_t *buf) 899{ 900 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(time_t)); 901} 902 903int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val) 904{ 905 BIGNUM *b; 906 907 if (val == NULL 908 || p == NULL 909 || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER) 910 return 0; 911 912 b = BN_native2bn(p->data, (int)p->data_size, *val); 913 if (b != NULL) { 914 *val = b; 915 return 1; 916 } 917 return 0; 918} 919 920int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val) 921{ 922 size_t bytes; 923 924 if (p == NULL) 925 return 0; 926 p->return_size = 0; 927 if (val == NULL || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER) 928 return 0; 929 930 /* For the moment, only positive values are permitted */ 931 if (BN_is_negative(val)) 932 return 0; 933 934 bytes = (size_t)BN_num_bytes(val); 935 /* We make sure that at least one byte is used, so zero is properly set */ 936 if (bytes == 0) 937 bytes++; 938 939 p->return_size = bytes; 940 if (p->data == NULL) 941 return 1; 942 if (p->data_size >= bytes) { 943 p->return_size = p->data_size; 944 return BN_bn2nativepad(val, p->data, p->data_size) >= 0; 945 } 946 return 0; 947} 948 949OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf, 950 size_t bsize) 951{ 952 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, 953 buf, bsize); 954} 955 956int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val) 957{ 958 int64_t i64; 959 uint64_t u64; 960 961 if (val == NULL || p == NULL) 962 return 0; 963 964 if (p->data_type == OSSL_PARAM_REAL) { 965 switch (p->data_size) { 966 case sizeof(double): 967 *val = *(const double *)p->data; 968 return 1; 969 } 970 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { 971 switch (p->data_size) { 972 case sizeof(uint32_t): 973 *val = *(const uint32_t *)p->data; 974 return 1; 975 case sizeof(uint64_t): 976 u64 = *(const uint64_t *)p->data; 977 if ((u64 >> real_shift()) == 0) { 978 *val = (double)u64; 979 return 1; 980 } 981 break; 982 } 983 } else if (p->data_type == OSSL_PARAM_INTEGER) { 984 switch (p->data_size) { 985 case sizeof(int32_t): 986 *val = *(const int32_t *)p->data; 987 return 1; 988 case sizeof(int64_t): 989 i64 = *(const int64_t *)p->data; 990 u64 = i64 < 0 ? -i64 : i64; 991 if ((u64 >> real_shift()) == 0) { 992 *val = 0.0 + i64; 993 return 1; 994 } 995 break; 996 } 997 } 998 return 0; 999} 1000 1001int OSSL_PARAM_set_double(OSSL_PARAM *p, double val) 1002{ 1003 if (p == NULL) 1004 return 0; 1005 p->return_size = 0; 1006 1007 if (p->data_type == OSSL_PARAM_REAL) { 1008 p->return_size = sizeof(double); 1009 if (p->data == NULL) 1010 return 1; 1011 switch (p->data_size) { 1012 case sizeof(double): 1013 *(double *)p->data = val; 1014 return 1; 1015 } 1016 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER 1017 && val == (uint64_t)val) { 1018 p->return_size = sizeof(double); 1019 if (p->data == NULL) 1020 return 1; 1021 switch (p->data_size) { 1022 case sizeof(uint32_t): 1023 if (val >= 0 && val <= UINT32_MAX) { 1024 p->return_size = sizeof(uint32_t); 1025 *(uint32_t *)p->data = (uint32_t)val; 1026 return 1; 1027 } 1028 break; 1029 case sizeof(uint64_t): 1030 if (val >= 0 1031 /* 1032 * By subtracting 65535 (2^16-1) we cancel the low order 1033 * 15 bits of UINT64_MAX to avoid using imprecise floating 1034 * point values. 1035 */ 1036 && val < (double)(UINT64_MAX - 65535) + 65536.0) { 1037 p->return_size = sizeof(uint64_t); 1038 *(uint64_t *)p->data = (uint64_t)val; 1039 return 1; 1040 } 1041 break; } 1042 } else if (p->data_type == OSSL_PARAM_INTEGER && val == (int64_t)val) { 1043 p->return_size = sizeof(double); 1044 if (p->data == NULL) 1045 return 1; 1046 switch (p->data_size) { 1047 case sizeof(int32_t): 1048 if (val >= INT32_MIN && val <= INT32_MAX) { 1049 p->return_size = sizeof(int32_t); 1050 *(int32_t *)p->data = (int32_t)val; 1051 return 1; 1052 } 1053 break; 1054 case sizeof(int64_t): 1055 if (val >= INT64_MIN 1056 /* 1057 * By subtracting 65535 (2^16-1) we cancel the low order 1058 * 15 bits of INT64_MAX to avoid using imprecise floating 1059 * point values. 1060 */ 1061 && val < (double)(INT64_MAX - 65535) + 65536.0) { 1062 p->return_size = sizeof(int64_t); 1063 *(int64_t *)p->data = (int64_t)val; 1064 return 1; 1065 } 1066 break; 1067 } 1068 } 1069 return 0; 1070} 1071 1072OSSL_PARAM OSSL_PARAM_construct_double(const char *key, double *buf) 1073{ 1074 return ossl_param_construct(key, OSSL_PARAM_REAL, buf, sizeof(double)); 1075} 1076 1077static int get_string_internal(const OSSL_PARAM *p, void **val, 1078 size_t *max_len, size_t *used_len, 1079 unsigned int type) 1080{ 1081 size_t sz, alloc_sz; 1082 1083 if ((val == NULL && used_len == NULL) || p == NULL || p->data_type != type) 1084 return 0; 1085 1086 sz = p->data_size; 1087 /* 1088 * If the input size is 0, or the input string needs NUL byte 1089 * termination, allocate an extra byte. 1090 */ 1091 alloc_sz = sz + (type == OSSL_PARAM_UTF8_STRING || sz == 0); 1092 1093 if (used_len != NULL) 1094 *used_len = sz; 1095 1096 if (p->data == NULL) 1097 return 0; 1098 1099 if (val == NULL) 1100 return 1; 1101 1102 if (*val == NULL) { 1103 char *const q = OPENSSL_malloc(alloc_sz); 1104 1105 if (q == NULL) 1106 return 0; 1107 *val = q; 1108 *max_len = alloc_sz; 1109 } 1110 1111 if (*max_len < sz) 1112 return 0; 1113 memcpy(*val, p->data, sz); 1114 return 1; 1115} 1116 1117int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len) 1118{ 1119 int ret = get_string_internal(p, (void **)val, &max_len, NULL, 1120 OSSL_PARAM_UTF8_STRING); 1121 1122 /* 1123 * We try to ensure that the copied string is terminated with a 1124 * NUL byte. That should be easy, just place a NUL byte at 1125 * |((char*)*val)[p->data_size]|. 1126 * Unfortunately, we have seen cases where |p->data_size| doesn't 1127 * correctly reflect the length of the string, and just happens 1128 * to be out of bounds according to |max_len|, so in that case, we 1129 * make the extra step of trying to find the true length of the 1130 * string that |p->data| points at, and use that as an index to 1131 * place the NUL byte in |*val|. 1132 */ 1133 size_t data_length = p->data_size; 1134 1135 if (ret == 0) 1136 return 0; 1137 if (data_length >= max_len) 1138 data_length = OPENSSL_strnlen(p->data, data_length); 1139 if (data_length >= max_len) 1140 return 0; /* No space for a terminating NUL byte */ 1141 (*val)[data_length] = '\0'; 1142 1143 return ret; 1144} 1145 1146int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len, 1147 size_t *used_len) 1148{ 1149 return get_string_internal(p, val, &max_len, used_len, 1150 OSSL_PARAM_OCTET_STRING); 1151} 1152 1153static int set_string_internal(OSSL_PARAM *p, const void *val, size_t len, 1154 unsigned int type) 1155{ 1156 p->return_size = len; 1157 if (p->data == NULL) 1158 return 1; 1159 if (p->data_type != type || p->data_size < len) 1160 return 0; 1161 1162 memcpy(p->data, val, len); 1163 /* If possible within the size of p->data, add a NUL terminator byte */ 1164 if (type == OSSL_PARAM_UTF8_STRING && p->data_size > len) 1165 ((char *)p->data)[len] = '\0'; 1166 return 1; 1167} 1168 1169int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val) 1170{ 1171 if (p == NULL) 1172 return 0; 1173 1174 p->return_size = 0; 1175 if (val == NULL) 1176 return 0; 1177 return set_string_internal(p, val, strlen(val), OSSL_PARAM_UTF8_STRING); 1178} 1179 1180int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val, 1181 size_t len) 1182{ 1183 if (p == NULL) 1184 return 0; 1185 1186 p->return_size = 0; 1187 if (val == NULL) 1188 return 0; 1189 return set_string_internal(p, val, len, OSSL_PARAM_OCTET_STRING); 1190} 1191 1192OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf, 1193 size_t bsize) 1194{ 1195 if (buf != NULL && bsize == 0) 1196 bsize = strlen(buf); 1197 return ossl_param_construct(key, OSSL_PARAM_UTF8_STRING, buf, bsize); 1198} 1199 1200OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf, 1201 size_t bsize) 1202{ 1203 return ossl_param_construct(key, OSSL_PARAM_OCTET_STRING, buf, bsize); 1204} 1205 1206static int get_ptr_internal(const OSSL_PARAM *p, const void **val, 1207 size_t *used_len, unsigned int type) 1208{ 1209 if (val == NULL || p == NULL || p->data_type != type) 1210 return 0; 1211 if (used_len != NULL) 1212 *used_len = p->data_size; 1213 *val = *(const void **)p->data; 1214 return 1; 1215} 1216 1217int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val) 1218{ 1219 return get_ptr_internal(p, (const void **)val, NULL, OSSL_PARAM_UTF8_PTR); 1220} 1221 1222int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val, 1223 size_t *used_len) 1224{ 1225 return get_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_PTR); 1226} 1227 1228static int set_ptr_internal(OSSL_PARAM *p, const void *val, 1229 unsigned int type, size_t len) 1230{ 1231 p->return_size = len; 1232 if (p->data_type != type) 1233 return 0; 1234 if (p->data != NULL) 1235 *(const void **)p->data = val; 1236 return 1; 1237} 1238 1239int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val) 1240{ 1241 if (p == NULL) 1242 return 0; 1243 p->return_size = 0; 1244 return set_ptr_internal(p, val, OSSL_PARAM_UTF8_PTR, 1245 val == NULL ? 0 : strlen(val)); 1246} 1247 1248int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val, 1249 size_t used_len) 1250{ 1251 if (p == NULL) 1252 return 0; 1253 p->return_size = 0; 1254 return set_ptr_internal(p, val, OSSL_PARAM_OCTET_PTR, used_len); 1255} 1256 1257OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf, 1258 size_t bsize) 1259{ 1260 return ossl_param_construct(key, OSSL_PARAM_UTF8_PTR, buf, bsize); 1261} 1262 1263OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf, 1264 size_t bsize) 1265{ 1266 return ossl_param_construct(key, OSSL_PARAM_OCTET_PTR, buf, bsize); 1267} 1268 1269OSSL_PARAM OSSL_PARAM_construct_end(void) 1270{ 1271 OSSL_PARAM end = OSSL_PARAM_END; 1272 1273 return end; 1274} 1275 1276static int get_string_ptr_internal(const OSSL_PARAM *p, const void **val, 1277 size_t *used_len, unsigned int type) 1278{ 1279 if (val == NULL || p == NULL || p->data_type != type) 1280 return 0; 1281 if (used_len != NULL) 1282 *used_len = p->data_size; 1283 *val = p->data; 1284 return 1; 1285} 1286 1287int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val) 1288{ 1289 return OSSL_PARAM_get_utf8_ptr(p, val) 1290 || get_string_ptr_internal(p, (const void **)val, NULL, 1291 OSSL_PARAM_UTF8_STRING); 1292} 1293 1294int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val, 1295 size_t *used_len) 1296{ 1297 return OSSL_PARAM_get_octet_ptr(p, val, used_len) 1298 || get_string_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_STRING); 1299} 1300