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
SECU_EnableWrap(PRBool enable)35 SECU_EnableWrap(PRBool enable)
36 {
37 wrapEnabled = enable;
38 }
39
40 PRBool
SECU_GetWrapEnabled(void)41 SECU_GetWrapEnabled(void)
42 {
43 return wrapEnabled;
44 }
45
46 void
SECU_PrintErrMsg(FILE * out,int level,const char * progName,const char * msg,...)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
SECU_PrintError(const char * progName,const char * msg,...)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
SECU_PrintSystemError(const char * progName,const char * msg,...)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
secu_StdinToItem(SECItem * dst)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
SECU_FileToItem(SECItem * dst,PRFileDesc * src)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
SECU_TextFileToItem(SECItem * dst,PRFileDesc * src)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
SECU_Indent(FILE * out,int level)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
SECU_Newline(FILE * out)239 SECU_Newline(FILE *out)
240 {
241 fprintf(out, "\n");
242 }
243
244 void
SECU_PrintAsHex(FILE * out,const SECItem * data,const char * m,int level)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
SECU_PrintBuf(FILE * out,const char * msg,const void * vp,int len)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
SECU_PrintInteger(FILE * out,const SECItem * i,const char * m,int level)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
HasShortDuplicate(int i,secuCommandFlag * a,int count)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
HasLongDuplicate(int i,secuCommandFlag * a,int count)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
HasNoDuplicates(secuCommandFlag * a,int count)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
SECU_ParseCommandLine(int argc,char ** argv,char * progName,const secuCommand * cmd)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 *
SECU_GetOptionArg(const secuCommand * cmd,int optionNum)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
SECU_PrintPRandOSError(const char * progName)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
SECU_StringToSignatureAlgTag(const char * alg)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
SECU_SECItemToHex(const SECItem * item,char * dst)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 sprintf(dst, "%02x", *src++);
683 }
684 *dst = '\0';
685 }
686 }
687
688 static unsigned char
nibble(char c)689 nibble(char c)
690 {
691 c = PORT_Tolower(c);
692 return (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 10 : -1;
693 }
694
695 SECStatus
SECU_SECItemHexStringToBinary(SECItem * srcdest)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 *
SECU_HexString2SECItem(PLArenaPool * arena,SECItem * item,const char * str)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 /* mapping between ECCurveName enum and SECOidTags */
782 static SECOidTag ecCurve_oid_map[] = {
783 SEC_OID_UNKNOWN, /* ECCurve_noName */
784 SEC_OID_ANSIX962_EC_PRIME192V1, /* ECCurve_NIST_P192 */
785 SEC_OID_SECG_EC_SECP224R1, /* ECCurve_NIST_P224 */
786 SEC_OID_ANSIX962_EC_PRIME256V1, /* ECCurve_NIST_P256 */
787 SEC_OID_SECG_EC_SECP384R1, /* ECCurve_NIST_P384 */
788 SEC_OID_SECG_EC_SECP521R1, /* ECCurve_NIST_P521 */
789 SEC_OID_SECG_EC_SECT163K1, /* ECCurve_NIST_K163 */
790 SEC_OID_SECG_EC_SECT163R1, /* ECCurve_NIST_B163 */
791 SEC_OID_SECG_EC_SECT233K1, /* ECCurve_NIST_K233 */
792 SEC_OID_SECG_EC_SECT233R1, /* ECCurve_NIST_B233 */
793 SEC_OID_SECG_EC_SECT283K1, /* ECCurve_NIST_K283 */
794 SEC_OID_SECG_EC_SECT283R1, /* ECCurve_NIST_B283 */
795 SEC_OID_SECG_EC_SECT409K1, /* ECCurve_NIST_K409 */
796 SEC_OID_SECG_EC_SECT409R1, /* ECCurve_NIST_B409 */
797 SEC_OID_SECG_EC_SECT571K1, /* ECCurve_NIST_K571 */
798 SEC_OID_SECG_EC_SECT571R1, /* ECCurve_NIST_B571 */
799 SEC_OID_ANSIX962_EC_PRIME192V2,
800 SEC_OID_ANSIX962_EC_PRIME192V3,
801 SEC_OID_ANSIX962_EC_PRIME239V1,
802 SEC_OID_ANSIX962_EC_PRIME239V2,
803 SEC_OID_ANSIX962_EC_PRIME239V3,
804 SEC_OID_ANSIX962_EC_C2PNB163V1,
805 SEC_OID_ANSIX962_EC_C2PNB163V2,
806 SEC_OID_ANSIX962_EC_C2PNB163V3,
807 SEC_OID_ANSIX962_EC_C2PNB176V1,
808 SEC_OID_ANSIX962_EC_C2TNB191V1,
809 SEC_OID_ANSIX962_EC_C2TNB191V2,
810 SEC_OID_ANSIX962_EC_C2TNB191V3,
811 SEC_OID_ANSIX962_EC_C2PNB208W1,
812 SEC_OID_ANSIX962_EC_C2TNB239V1,
813 SEC_OID_ANSIX962_EC_C2TNB239V2,
814 SEC_OID_ANSIX962_EC_C2TNB239V3,
815 SEC_OID_ANSIX962_EC_C2PNB272W1,
816 SEC_OID_ANSIX962_EC_C2PNB304W1,
817 SEC_OID_ANSIX962_EC_C2TNB359V1,
818 SEC_OID_ANSIX962_EC_C2PNB368W1,
819 SEC_OID_ANSIX962_EC_C2TNB431R1,
820 SEC_OID_SECG_EC_SECP112R1,
821 SEC_OID_SECG_EC_SECP112R2,
822 SEC_OID_SECG_EC_SECP128R1,
823 SEC_OID_SECG_EC_SECP128R2,
824 SEC_OID_SECG_EC_SECP160K1,
825 SEC_OID_SECG_EC_SECP160R1,
826 SEC_OID_SECG_EC_SECP160R2,
827 SEC_OID_SECG_EC_SECP192K1,
828 SEC_OID_SECG_EC_SECP224K1,
829 SEC_OID_SECG_EC_SECP256K1,
830 SEC_OID_SECG_EC_SECT113R1,
831 SEC_OID_SECG_EC_SECT113R2,
832 SEC_OID_SECG_EC_SECT131R1,
833 SEC_OID_SECG_EC_SECT131R2,
834 SEC_OID_SECG_EC_SECT163R1,
835 SEC_OID_SECG_EC_SECT193R1,
836 SEC_OID_SECG_EC_SECT193R2,
837 SEC_OID_SECG_EC_SECT239K1,
838 SEC_OID_UNKNOWN, /* ECCurve_WTLS_1 */
839 SEC_OID_UNKNOWN, /* ECCurve_WTLS_8 */
840 SEC_OID_UNKNOWN, /* ECCurve_WTLS_9 */
841 SEC_OID_CURVE25519,
842 SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
843 };
844
845 SECStatus
SECU_ecName2params(ECCurveName curve,SECItem * params)846 SECU_ecName2params(ECCurveName curve, SECItem *params)
847 {
848 SECOidData *oidData = NULL;
849
850 if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve) ||
851 ((oidData = SECOID_FindOIDByTag(ecCurve_oid_map[curve])) == NULL)) {
852 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
853 return SECFailure;
854 }
855
856 if (SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len)) == NULL) {
857 return SECFailure;
858 }
859 /*
860 * params->data needs to contain the ASN encoding of an object ID (OID)
861 * representing the named curve. The actual OID is in
862 * oidData->oid.data so we simply prepend 0x06 and OID length
863 */
864 params->data[0] = SEC_ASN1_OBJECT_ID;
865 params->data[1] = oidData->oid.len;
866 memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
867
868 return SECSuccess;
869 }
870