basicutil.c (21371B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 ** secutil.c - various functions used by security stuff 6 ** 7 */ 8 9 #include "prtypes.h" 10 #include "prtime.h" 11 #include "prlong.h" 12 #include "prerror.h" 13 #include "prprf.h" 14 #include "plgetopt.h" 15 #include "prenv.h" 16 #include "prnetdb.h" 17 18 #include "basicutil.h" 19 #include <stdarg.h> 20 #include <stddef.h> 21 #include <sys/stat.h> 22 #include <errno.h> 23 24 #ifdef XP_UNIX 25 #include <unistd.h> 26 #endif 27 28 #include "secoid.h" 29 30 extern long DER_GetInteger(const SECItem *src); 31 32 static PRBool wrapEnabled = PR_TRUE; 33 34 void 35 SECU_EnableWrap(PRBool enable) 36 { 37 wrapEnabled = enable; 38 } 39 40 PRBool 41 SECU_GetWrapEnabled(void) 42 { 43 return wrapEnabled; 44 } 45 46 void 47 SECU_PrintErrMsg(FILE *out, int level, const char *progName, const char *msg, 48 ...) 49 { 50 va_list args; 51 PRErrorCode err = PORT_GetError(); 52 const char *errString = PORT_ErrorToString(err); 53 54 va_start(args, msg); 55 56 SECU_Indent(out, level); 57 fprintf(out, "%s: ", progName); 58 vfprintf(out, msg, args); 59 if (errString != NULL && PORT_Strlen(errString) > 0) 60 fprintf(out, ": %s\n", errString); 61 else 62 fprintf(out, ": error %d\n", (int)err); 63 64 va_end(args); 65 } 66 67 void 68 SECU_PrintError(const char *progName, const char *msg, ...) 69 { 70 va_list args; 71 PRErrorCode err = PORT_GetError(); 72 const char *errName = PR_ErrorToName(err); 73 const char *errString = PR_ErrorToString(err, 0); 74 75 va_start(args, msg); 76 77 fprintf(stderr, "%s: ", progName); 78 vfprintf(stderr, msg, args); 79 80 if (errName != NULL) { 81 fprintf(stderr, ": %s", errName); 82 } else { 83 fprintf(stderr, ": error %d", (int)err); 84 } 85 86 if (errString != NULL && PORT_Strlen(errString) > 0) 87 fprintf(stderr, ": %s\n", errString); 88 89 va_end(args); 90 } 91 92 void 93 SECU_PrintSystemError(const char *progName, const char *msg, ...) 94 { 95 va_list args; 96 97 va_start(args, msg); 98 fprintf(stderr, "%s: ", progName); 99 vfprintf(stderr, msg, args); 100 fprintf(stderr, ": %s\n", strerror(errno)); 101 va_end(args); 102 } 103 104 SECStatus 105 secu_StdinToItem(SECItem *dst) 106 { 107 unsigned char buf[1000]; 108 PRInt32 numBytes; 109 PRBool notDone = PR_TRUE; 110 111 dst->len = 0; 112 dst->data = NULL; 113 114 while (notDone) { 115 numBytes = PR_Read(PR_STDIN, buf, sizeof(buf)); 116 117 if (numBytes < 0) { 118 return SECFailure; 119 } 120 121 if (numBytes == 0) 122 break; 123 124 if (dst->data) { 125 unsigned char *p = dst->data; 126 dst->data = (unsigned char *)PORT_Realloc(p, dst->len + numBytes); 127 if (!dst->data) { 128 PORT_Free(p); 129 } 130 } else { 131 dst->data = (unsigned char *)PORT_Alloc(numBytes); 132 } 133 if (!dst->data) { 134 return SECFailure; 135 } 136 PORT_Memcpy(dst->data + dst->len, buf, numBytes); 137 dst->len += numBytes; 138 } 139 140 return SECSuccess; 141 } 142 143 SECStatus 144 SECU_FileToItem(SECItem *dst, PRFileDesc *src) 145 { 146 PRFileInfo info; 147 PRInt32 numBytes; 148 PRStatus prStatus; 149 150 if (src == PR_STDIN) 151 return secu_StdinToItem(dst); 152 153 prStatus = PR_GetOpenFileInfo(src, &info); 154 155 if (prStatus != PR_SUCCESS) { 156 PORT_SetError(SEC_ERROR_IO); 157 return SECFailure; 158 } 159 160 /* XXX workaround for 3.1, not all utils zero dst before sending */ 161 dst->data = 0; 162 if (!SECITEM_AllocItem(NULL, dst, info.size)) 163 goto loser; 164 165 numBytes = PR_Read(src, dst->data, info.size); 166 if (numBytes != info.size) { 167 PORT_SetError(SEC_ERROR_IO); 168 goto loser; 169 } 170 171 return SECSuccess; 172 loser: 173 SECITEM_FreeItem(dst, PR_FALSE); 174 dst->data = NULL; 175 return SECFailure; 176 } 177 178 SECStatus 179 SECU_TextFileToItem(SECItem *dst, PRFileDesc *src) 180 { 181 PRFileInfo info; 182 PRInt32 numBytes; 183 PRStatus prStatus; 184 unsigned char *buf; 185 186 if (src == PR_STDIN) 187 return secu_StdinToItem(dst); 188 189 prStatus = PR_GetOpenFileInfo(src, &info); 190 191 if (prStatus != PR_SUCCESS) { 192 PORT_SetError(SEC_ERROR_IO); 193 return SECFailure; 194 } 195 196 buf = (unsigned char *)PORT_Alloc(info.size); 197 if (!buf) 198 return SECFailure; 199 200 numBytes = PR_Read(src, buf, info.size); 201 if (numBytes != info.size) { 202 PORT_SetError(SEC_ERROR_IO); 203 goto loser; 204 } 205 206 if (buf[numBytes - 1] == '\n') 207 numBytes--; 208 #ifdef _WINDOWS 209 if (buf[numBytes - 1] == '\r') 210 numBytes--; 211 #endif 212 213 /* XXX workaround for 3.1, not all utils zero dst before sending */ 214 dst->data = 0; 215 if (!SECITEM_AllocItem(NULL, dst, numBytes)) 216 goto loser; 217 218 memcpy(dst->data, buf, numBytes); 219 220 PORT_Free(buf); 221 return SECSuccess; 222 loser: 223 PORT_Free(buf); 224 return SECFailure; 225 } 226 227 #define INDENT_MULT 4 228 void 229 SECU_Indent(FILE *out, int level) 230 { 231 int i; 232 233 for (i = 0; i < level; i++) { 234 fprintf(out, " "); 235 } 236 } 237 238 void 239 SECU_Newline(FILE *out) 240 { 241 fprintf(out, "\n"); 242 } 243 244 void 245 SECU_PrintAsHex(FILE *out, const SECItem *data, const char *m, int level) 246 { 247 unsigned i; 248 int column = 0; 249 PRBool isString = PR_TRUE; 250 PRBool isWhiteSpace = PR_TRUE; 251 PRBool printedHex = PR_FALSE; 252 unsigned int limit = 15; 253 254 if (m) { 255 SECU_Indent(out, level); 256 fprintf(out, "%s:", m); 257 level++; 258 if (wrapEnabled) 259 fprintf(out, "\n"); 260 } 261 262 if (wrapEnabled) { 263 SECU_Indent(out, level); 264 column = level * INDENT_MULT; 265 } 266 if (!data->len) { 267 fprintf(out, "(empty)\n"); 268 return; 269 } 270 /* take a pass to see if it's all printable. */ 271 for (i = 0; i < data->len; i++) { 272 unsigned char val = data->data[i]; 273 if (!val || !isprint(val)) { 274 isString = PR_FALSE; 275 break; 276 } 277 if (isWhiteSpace && !isspace(val)) { 278 isWhiteSpace = PR_FALSE; 279 } 280 } 281 282 /* Short values, such as bit strings (which are printed with this 283 ** function) often look like strings, but we want to see the bits. 284 ** so this test assures that short values will be printed in hex, 285 ** perhaps in addition to being printed as strings. 286 ** The threshold size (4 bytes) is arbitrary. 287 */ 288 if (!isString || data->len <= 4) { 289 for (i = 0; i < data->len; i++) { 290 if (i != data->len - 1) { 291 fprintf(out, "%02x:", data->data[i]); 292 column += 3; 293 } else { 294 fprintf(out, "%02x", data->data[i]); 295 column += 2; 296 break; 297 } 298 if (wrapEnabled && 299 (column > 76 || (i % 16 == limit))) { 300 SECU_Newline(out); 301 SECU_Indent(out, level); 302 column = level * INDENT_MULT; 303 limit = i % 16; 304 } 305 } 306 printedHex = PR_TRUE; 307 } 308 if (isString && !isWhiteSpace) { 309 if (printedHex != PR_FALSE) { 310 SECU_Newline(out); 311 SECU_Indent(out, level); 312 column = level * INDENT_MULT; 313 } 314 for (i = 0; i < data->len; i++) { 315 unsigned char val = data->data[i]; 316 317 if (val) { 318 fprintf(out, "%c", val); 319 column++; 320 } else { 321 column = 77; 322 } 323 if (wrapEnabled && column > 76) { 324 SECU_Newline(out); 325 SECU_Indent(out, level); 326 column = level * INDENT_MULT; 327 } 328 } 329 } 330 331 if (column != level * INDENT_MULT) { 332 SECU_Newline(out); 333 } 334 } 335 336 const char *hex = "0123456789abcdef"; 337 338 const char printable[257] = { 339 "................" /* 0x */ 340 "................" /* 1x */ 341 " !\"#$%&'()*+,-./" /* 2x */ 342 "0123456789:;<=>?" /* 3x */ 343 "@ABCDEFGHIJKLMNO" /* 4x */ 344 "PQRSTUVWXYZ[\\]^_" /* 5x */ 345 "`abcdefghijklmno" /* 6x */ 346 "pqrstuvwxyz{|}~." /* 7x */ 347 "................" /* 8x */ 348 "................" /* 9x */ 349 "................" /* ax */ 350 "................" /* bx */ 351 "................" /* cx */ 352 "................" /* dx */ 353 "................" /* ex */ 354 "................" /* fx */ 355 }; 356 357 void 358 SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len) 359 { 360 const unsigned char *cp = (const unsigned char *)vp; 361 char buf[80]; 362 char *bp; 363 char *ap; 364 365 fprintf(out, "%s [Len: %d]\n", msg, len); 366 memset(buf, ' ', sizeof buf); 367 bp = buf; 368 ap = buf + 50; 369 while (--len >= 0) { 370 unsigned char ch = *cp++; 371 *bp++ = hex[(ch >> 4) & 0xf]; 372 *bp++ = hex[ch & 0xf]; 373 *bp++ = ' '; 374 *ap++ = printable[ch]; 375 if (ap - buf >= 66) { 376 *ap = 0; 377 fprintf(out, " %s\n", buf); 378 memset(buf, ' ', sizeof buf); 379 bp = buf; 380 ap = buf + 50; 381 } 382 } 383 if (bp > buf) { 384 *ap = 0; 385 fprintf(out, " %s\n", buf); 386 } 387 } 388 389 /* This expents i->data[0] to be the MSB of the integer. 390 ** if you want to print a DER-encoded integer (with the tag and length) 391 ** call SECU_PrintEncodedInteger(); 392 */ 393 void 394 SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, int level) 395 { 396 int iv; 397 398 if (!i || !i->len || !i->data) { 399 SECU_Indent(out, level); 400 if (m) { 401 fprintf(out, "%s: (null)\n", m); 402 } else { 403 fprintf(out, "(null)\n"); 404 } 405 } else if (i->len > 4) { 406 SECU_PrintAsHex(out, i, m, level); 407 } else { 408 if (i->type == siUnsignedInteger && *i->data & 0x80) { 409 /* Make sure i->data has zero in the highest bite 410 * if i->data is an unsigned integer */ 411 SECItem tmpI; 412 char data[] = { 0, 0, 0, 0, 0 }; 413 414 PORT_Memcpy(data + 1, i->data, i->len); 415 tmpI.len = i->len + 1; 416 tmpI.data = (void *)data; 417 418 iv = DER_GetInteger(&tmpI); 419 } else { 420 iv = DER_GetInteger(i); 421 } 422 SECU_Indent(out, level); 423 if (m) { 424 fprintf(out, "%s: %d (0x%x)\n", m, iv, iv); 425 } else { 426 fprintf(out, "%d (0x%x)\n", iv, iv); 427 } 428 } 429 } 430 431 #if defined(DEBUG) || defined(FORCE_PR_ASSERT) 432 /* Returns true iff a[i].flag has a duplicate in a[i+1 : count-1] */ 433 static PRBool 434 HasShortDuplicate(int i, secuCommandFlag *a, int count) 435 { 436 char target = a[i].flag; 437 int j; 438 439 /* duplicate '\0' flags are okay, they are used with long forms */ 440 for (j = i + 1; j < count; j++) { 441 if (a[j].flag && a[j].flag == target) { 442 return PR_TRUE; 443 } 444 } 445 return PR_FALSE; 446 } 447 448 /* Returns true iff a[i].longform has a duplicate in a[i+1 : count-1] */ 449 static PRBool 450 HasLongDuplicate(int i, secuCommandFlag *a, int count) 451 { 452 int j; 453 char *target = a[i].longform; 454 455 if (!target) 456 return PR_FALSE; 457 458 for (j = i + 1; j < count; j++) { 459 if (a[j].longform && strcmp(a[j].longform, target) == 0) { 460 return PR_TRUE; 461 } 462 } 463 return PR_FALSE; 464 } 465 466 /* Returns true iff a has no short or long form duplicates 467 */ 468 PRBool 469 HasNoDuplicates(secuCommandFlag *a, int count) 470 { 471 int i; 472 473 for (i = 0; i < count; i++) { 474 if (a[i].flag && HasShortDuplicate(i, a, count)) { 475 return PR_FALSE; 476 } 477 if (a[i].longform && HasLongDuplicate(i, a, count)) { 478 return PR_FALSE; 479 } 480 } 481 return PR_TRUE; 482 } 483 #endif 484 485 SECStatus 486 SECU_ParseCommandLine(int argc, char **argv, char *progName, 487 const secuCommand *cmd) 488 { 489 PRBool found; 490 PLOptState *optstate; 491 PLOptStatus status; 492 char *optstring; 493 PLLongOpt *longopts = NULL; 494 int i, j; 495 int lcmd = 0, lopt = 0; 496 497 PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands)); 498 PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions)); 499 500 optstring = (char *)PORT_Alloc(cmd->numCommands + 2 * cmd->numOptions + 1); 501 if (optstring == NULL) 502 return SECFailure; 503 504 j = 0; 505 for (i = 0; i < cmd->numCommands; i++) { 506 if (cmd->commands[i].flag) /* single character option ? */ 507 optstring[j++] = cmd->commands[i].flag; 508 if (cmd->commands[i].longform) 509 lcmd++; 510 } 511 for (i = 0; i < cmd->numOptions; i++) { 512 if (cmd->options[i].flag) { 513 optstring[j++] = cmd->options[i].flag; 514 if (cmd->options[i].needsArg) 515 optstring[j++] = ':'; 516 } 517 if (cmd->options[i].longform) 518 lopt++; 519 } 520 521 optstring[j] = '\0'; 522 523 if (lcmd + lopt > 0) { 524 longopts = PORT_NewArray(PLLongOpt, lcmd + lopt + 1); 525 if (!longopts) { 526 PORT_Free(optstring); 527 return SECFailure; 528 } 529 530 j = 0; 531 for (i = 0; j < lcmd && i < cmd->numCommands; i++) { 532 if (cmd->commands[i].longform) { 533 longopts[j].longOptName = cmd->commands[i].longform; 534 longopts[j].longOption = 0; 535 longopts[j++].valueRequired = cmd->commands[i].needsArg; 536 } 537 } 538 lopt += lcmd; 539 for (i = 0; j < lopt && i < cmd->numOptions; i++) { 540 if (cmd->options[i].longform) { 541 longopts[j].longOptName = cmd->options[i].longform; 542 longopts[j].longOption = 0; 543 longopts[j++].valueRequired = cmd->options[i].needsArg; 544 } 545 } 546 longopts[j].longOptName = NULL; 547 } 548 549 optstate = PL_CreateLongOptState(argc, argv, optstring, longopts); 550 if (!optstate) { 551 PORT_Free(optstring); 552 PORT_Free(longopts); 553 return SECFailure; 554 } 555 /* Parse command line arguments */ 556 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 557 const char *optstatelong; 558 char option = optstate->option; 559 560 /* positional parameter, single-char option or long opt? */ 561 if (optstate->longOptIndex == -1) { 562 /* not a long opt */ 563 if (option == '\0') 564 continue; /* it's a positional parameter */ 565 optstatelong = ""; 566 } else { 567 /* long opt */ 568 if (option == '\0') 569 option = '\377'; /* force unequal with all flags */ 570 optstatelong = longopts[optstate->longOptIndex].longOptName; 571 } 572 573 found = PR_FALSE; 574 575 for (i = 0; i < cmd->numCommands; i++) { 576 if (cmd->commands[i].flag == option || 577 cmd->commands[i].longform == optstatelong) { 578 cmd->commands[i].activated = PR_TRUE; 579 if (optstate->value) { 580 cmd->commands[i].arg = (char *)optstate->value; 581 } 582 found = PR_TRUE; 583 break; 584 } 585 } 586 587 if (found) 588 continue; 589 590 for (i = 0; i < cmd->numOptions; i++) { 591 if (cmd->options[i].flag == option || 592 cmd->options[i].longform == optstatelong) { 593 cmd->options[i].activated = PR_TRUE; 594 if (optstate->value) { 595 cmd->options[i].arg = (char *)optstate->value; 596 } else if (cmd->options[i].needsArg) { 597 status = PL_OPT_BAD; 598 goto loser; 599 } 600 found = PR_TRUE; 601 break; 602 } 603 } 604 605 if (!found) { 606 status = PL_OPT_BAD; 607 break; 608 } 609 } 610 611 loser: 612 PL_DestroyOptState(optstate); 613 PORT_Free(optstring); 614 if (longopts) 615 PORT_Free(longopts); 616 if (status == PL_OPT_BAD) 617 return SECFailure; 618 return SECSuccess; 619 } 620 621 char * 622 SECU_GetOptionArg(const secuCommand *cmd, int optionNum) 623 { 624 if (optionNum < 0 || optionNum >= cmd->numOptions) 625 return NULL; 626 if (cmd->options[optionNum].activated) 627 return PL_strdup(cmd->options[optionNum].arg); 628 else 629 return NULL; 630 } 631 632 void 633 SECU_PrintPRandOSError(const char *progName) 634 { 635 char buffer[513]; 636 PRInt32 errLenInt = PR_GetErrorTextLength(); 637 size_t errLen = errLenInt < 0 ? 0 : (size_t)errLenInt; 638 if (errLen > 0 && errLen < sizeof buffer) { 639 PR_GetErrorText(buffer); 640 } 641 SECU_PrintError(progName, "function failed"); 642 if (errLen > 0 && errLen < sizeof buffer) { 643 PR_fprintf(PR_STDERR, "\t%s\n", buffer); 644 } 645 } 646 647 SECOidTag 648 SECU_StringToSignatureAlgTag(const char *alg) 649 { 650 SECOidTag hashAlgTag = SEC_OID_UNKNOWN; 651 652 if (alg) { 653 if (!PL_strcmp(alg, "MD2")) { 654 hashAlgTag = SEC_OID_MD2; 655 } else if (!PL_strcmp(alg, "MD4")) { 656 hashAlgTag = SEC_OID_MD4; 657 } else if (!PL_strcmp(alg, "MD5")) { 658 hashAlgTag = SEC_OID_MD5; 659 } else if (!PL_strcmp(alg, "SHA1")) { 660 hashAlgTag = SEC_OID_SHA1; 661 } else if (!PL_strcmp(alg, "SHA224")) { 662 hashAlgTag = SEC_OID_SHA224; 663 } else if (!PL_strcmp(alg, "SHA256")) { 664 hashAlgTag = SEC_OID_SHA256; 665 } else if (!PL_strcmp(alg, "SHA384")) { 666 hashAlgTag = SEC_OID_SHA384; 667 } else if (!PL_strcmp(alg, "SHA512")) { 668 hashAlgTag = SEC_OID_SHA512; 669 } 670 } 671 return hashAlgTag; 672 } 673 674 /* Caller ensures that dst is at least item->len*2+1 bytes long */ 675 void 676 SECU_SECItemToHex(const SECItem *item, char *dst) 677 { 678 if (dst && item && item->data) { 679 unsigned char *src = item->data; 680 unsigned int len = item->len; 681 for (; len > 0; --len, dst += 2) { 682 snprintf(dst, 3, "%02x", *src++); 683 } 684 } 685 } 686 687 static unsigned char 688 nibble(char c) 689 { 690 c = PORT_Tolower((unsigned char)c); 691 return (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 10 692 : -1; 693 } 694 695 SECStatus 696 SECU_SECItemHexStringToBinary(SECItem *srcdest) 697 { 698 unsigned int i; 699 700 if (!srcdest) { 701 PORT_SetError(SEC_ERROR_INVALID_ARGS); 702 return SECFailure; 703 } 704 if (srcdest->len < 4 || (srcdest->len % 2)) { 705 /* too short to convert, or even number of characters */ 706 PORT_SetError(SEC_ERROR_BAD_DATA); 707 return SECFailure; 708 } 709 if (PORT_Strncasecmp((const char *)srcdest->data, "0x", 2)) { 710 /* wrong prefix */ 711 PORT_SetError(SEC_ERROR_BAD_DATA); 712 return SECFailure; 713 } 714 715 /* 1st pass to check for hex characters */ 716 for (i = 2; i < srcdest->len; i++) { 717 char c = PORT_Tolower(srcdest->data[i]); 718 if (!((c >= '0' && c <= '9') || 719 (c >= 'a' && c <= 'f'))) { 720 PORT_SetError(SEC_ERROR_BAD_DATA); 721 return SECFailure; 722 } 723 } 724 725 /* 2nd pass to convert */ 726 for (i = 2; i < srcdest->len; i += 2) { 727 srcdest->data[(i - 2) / 2] = (nibble(srcdest->data[i]) << 4) + 728 nibble(srcdest->data[i + 1]); 729 } 730 731 /* adjust length */ 732 srcdest->len -= 2; 733 srcdest->len /= 2; 734 return SECSuccess; 735 } 736 737 SECItem * 738 SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str) 739 { 740 int i = 0; 741 int byteval = 0; 742 int tmp = PORT_Strlen(str); 743 744 PORT_Assert(item); 745 746 if ((tmp % 2) != 0) { 747 PORT_SetError(SEC_ERROR_INVALID_ARGS); 748 return NULL; 749 } 750 751 item = SECITEM_AllocItem(arena, item, tmp / 2); 752 if (item == NULL) { 753 return NULL; 754 } 755 756 while (str[i]) { 757 if ((str[i] >= '0') && (str[i] <= '9')) { 758 tmp = str[i] - '0'; 759 } else if ((str[i] >= 'a') && (str[i] <= 'f')) { 760 tmp = str[i] - 'a' + 10; 761 } else if ((str[i] >= 'A') && (str[i] <= 'F')) { 762 tmp = str[i] - 'A' + 10; 763 } else { 764 if (!arena) { 765 SECITEM_FreeItem(item, PR_FALSE); 766 } 767 return NULL; 768 } 769 770 byteval = byteval * 16 + tmp; 771 if ((i % 2) != 0) { 772 item->data[i / 2] = byteval; 773 byteval = 0; 774 } 775 i++; 776 } 777 778 return item; 779 } 780 781 SECStatus 782 SECU_ecName2params(ECCurveName curve, SECItem *params) 783 { 784 SECOidTag oidTag; 785 SECOidData *oidData = NULL; 786 787 switch (curve) { 788 case ECCurve_NIST_P256: 789 oidTag = SEC_OID_ANSIX962_EC_PRIME256V1; 790 break; 791 case ECCurve_NIST_P384: 792 oidTag = SEC_OID_SECG_EC_SECP384R1; 793 break; 794 case ECCurve_NIST_P521: 795 oidTag = SEC_OID_SECG_EC_SECP521R1; 796 break; 797 case ECCurve25519: 798 oidTag = SEC_OID_CURVE25519; 799 break; 800 case ECCurve_Ed25519: 801 oidTag = SEC_OID_ED25519_PUBLIC_KEY; 802 break; 803 default: 804 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 805 return SECFailure; 806 } 807 808 oidData = SECOID_FindOIDByTag(oidTag); 809 if (oidData == NULL) { 810 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 811 return SECFailure; 812 } 813 814 if (SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len)) == NULL) { 815 return SECFailure; 816 } 817 /* 818 * params->data needs to contain the ASN encoding of an object ID (OID) 819 * representing the named curve. The actual OID is in 820 * oidData->oid.data so we simply prepend 0x06 and OID length 821 */ 822 params->data[0] = SEC_ASN1_OBJECT_ID; 823 params->data[1] = oidData->oid.len; 824 memcpy(params->data + 2, oidData->oid.data, oidData->oid.len); 825 826 return SECSuccess; 827 }