1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/lib/basicutil.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,725 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 +** secutil.c - various functions used by security stuff 1.9 +** 1.10 +*/ 1.11 + 1.12 +#include "prtypes.h" 1.13 +#include "prtime.h" 1.14 +#include "prlong.h" 1.15 +#include "prerror.h" 1.16 +#include "prprf.h" 1.17 +#include "plgetopt.h" 1.18 +#include "prenv.h" 1.19 +#include "prnetdb.h" 1.20 + 1.21 +#include "basicutil.h" 1.22 +#include <stdarg.h> 1.23 +#include <sys/stat.h> 1.24 +#include <errno.h> 1.25 + 1.26 +#ifdef XP_UNIX 1.27 +#include <unistd.h> 1.28 +#endif 1.29 + 1.30 +#include "secoid.h" 1.31 + 1.32 +extern long DER_GetInteger(const SECItem *src); 1.33 + 1.34 +static PRBool wrapEnabled = PR_TRUE; 1.35 + 1.36 +void 1.37 +SECU_EnableWrap(PRBool enable) 1.38 +{ 1.39 + wrapEnabled = enable; 1.40 +} 1.41 + 1.42 +PRBool 1.43 +SECU_GetWrapEnabled(void) 1.44 +{ 1.45 + return wrapEnabled; 1.46 +} 1.47 + 1.48 +void 1.49 +SECU_PrintErrMsg(FILE *out, int level, const char *progName, const char *msg, 1.50 + ...) 1.51 +{ 1.52 + va_list args; 1.53 + PRErrorCode err = PORT_GetError(); 1.54 + const char * errString = PORT_ErrorToString(err); 1.55 + 1.56 + va_start(args, msg); 1.57 + 1.58 + SECU_Indent(out, level); 1.59 + fprintf(out, "%s: ", progName); 1.60 + vfprintf(out, msg, args); 1.61 + if (errString != NULL && PORT_Strlen(errString) > 0) 1.62 + fprintf(out, ": %s\n", errString); 1.63 + else 1.64 + fprintf(out, ": error %d\n", (int)err); 1.65 + 1.66 + va_end(args); 1.67 +} 1.68 + 1.69 +void 1.70 +SECU_PrintError(const char *progName, const char *msg, ...) 1.71 +{ 1.72 + va_list args; 1.73 + PRErrorCode err = PORT_GetError(); 1.74 + const char * errName = PR_ErrorToName(err); 1.75 + const char * errString = PR_ErrorToString(err, 0); 1.76 + 1.77 + va_start(args, msg); 1.78 + 1.79 + fprintf(stderr, "%s: ", progName); 1.80 + vfprintf(stderr, msg, args); 1.81 + 1.82 + if (errName != NULL) { 1.83 + fprintf(stderr, ": %s", errName); 1.84 + } else { 1.85 + fprintf(stderr, ": error %d", (int)err); 1.86 + } 1.87 + 1.88 + if (errString != NULL && PORT_Strlen(errString) > 0) 1.89 + fprintf(stderr, ": %s\n", errString); 1.90 + 1.91 + va_end(args); 1.92 +} 1.93 + 1.94 +void 1.95 +SECU_PrintSystemError(const char *progName, const char *msg, ...) 1.96 +{ 1.97 + va_list args; 1.98 + 1.99 + va_start(args, msg); 1.100 + fprintf(stderr, "%s: ", progName); 1.101 + vfprintf(stderr, msg, args); 1.102 + fprintf(stderr, ": %s\n", strerror(errno)); 1.103 + va_end(args); 1.104 +} 1.105 + 1.106 +SECStatus 1.107 +secu_StdinToItem(SECItem *dst) 1.108 +{ 1.109 + unsigned char buf[1000]; 1.110 + PRInt32 numBytes; 1.111 + PRBool notDone = PR_TRUE; 1.112 + 1.113 + dst->len = 0; 1.114 + dst->data = NULL; 1.115 + 1.116 + while (notDone) { 1.117 + numBytes = PR_Read(PR_STDIN, buf, sizeof(buf)); 1.118 + 1.119 + if (numBytes < 0) { 1.120 + return SECFailure; 1.121 + } 1.122 + 1.123 + if (numBytes == 0) 1.124 + break; 1.125 + 1.126 + if (dst->data) { 1.127 + unsigned char * p = dst->data; 1.128 + dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes); 1.129 + if (!dst->data) { 1.130 + PORT_Free(p); 1.131 + } 1.132 + } else { 1.133 + dst->data = (unsigned char*)PORT_Alloc(numBytes); 1.134 + } 1.135 + if (!dst->data) { 1.136 + return SECFailure; 1.137 + } 1.138 + PORT_Memcpy(dst->data + dst->len, buf, numBytes); 1.139 + dst->len += numBytes; 1.140 + } 1.141 + 1.142 + return SECSuccess; 1.143 +} 1.144 + 1.145 +SECStatus 1.146 +SECU_FileToItem(SECItem *dst, PRFileDesc *src) 1.147 +{ 1.148 + PRFileInfo info; 1.149 + PRInt32 numBytes; 1.150 + PRStatus prStatus; 1.151 + 1.152 + if (src == PR_STDIN) 1.153 + return secu_StdinToItem(dst); 1.154 + 1.155 + prStatus = PR_GetOpenFileInfo(src, &info); 1.156 + 1.157 + if (prStatus != PR_SUCCESS) { 1.158 + PORT_SetError(SEC_ERROR_IO); 1.159 + return SECFailure; 1.160 + } 1.161 + 1.162 + /* XXX workaround for 3.1, not all utils zero dst before sending */ 1.163 + dst->data = 0; 1.164 + if (!SECITEM_AllocItem(NULL, dst, info.size)) 1.165 + goto loser; 1.166 + 1.167 + numBytes = PR_Read(src, dst->data, info.size); 1.168 + if (numBytes != info.size) { 1.169 + PORT_SetError(SEC_ERROR_IO); 1.170 + goto loser; 1.171 + } 1.172 + 1.173 + return SECSuccess; 1.174 +loser: 1.175 + SECITEM_FreeItem(dst, PR_FALSE); 1.176 + dst->data = NULL; 1.177 + return SECFailure; 1.178 +} 1.179 + 1.180 +SECStatus 1.181 +SECU_TextFileToItem(SECItem *dst, PRFileDesc *src) 1.182 +{ 1.183 + PRFileInfo info; 1.184 + PRInt32 numBytes; 1.185 + PRStatus prStatus; 1.186 + unsigned char *buf; 1.187 + 1.188 + if (src == PR_STDIN) 1.189 + return secu_StdinToItem(dst); 1.190 + 1.191 + prStatus = PR_GetOpenFileInfo(src, &info); 1.192 + 1.193 + if (prStatus != PR_SUCCESS) { 1.194 + PORT_SetError(SEC_ERROR_IO); 1.195 + return SECFailure; 1.196 + } 1.197 + 1.198 + buf = (unsigned char*)PORT_Alloc(info.size); 1.199 + if (!buf) 1.200 + return SECFailure; 1.201 + 1.202 + numBytes = PR_Read(src, buf, info.size); 1.203 + if (numBytes != info.size) { 1.204 + PORT_SetError(SEC_ERROR_IO); 1.205 + goto loser; 1.206 + } 1.207 + 1.208 + if (buf[numBytes-1] == '\n') numBytes--; 1.209 +#ifdef _WINDOWS 1.210 + if (buf[numBytes-1] == '\r') numBytes--; 1.211 +#endif 1.212 + 1.213 + /* XXX workaround for 3.1, not all utils zero dst before sending */ 1.214 + dst->data = 0; 1.215 + if (!SECITEM_AllocItem(NULL, dst, numBytes)) 1.216 + goto loser; 1.217 + 1.218 + memcpy(dst->data, buf, numBytes); 1.219 + 1.220 + PORT_Free(buf); 1.221 + return SECSuccess; 1.222 +loser: 1.223 + PORT_Free(buf); 1.224 + return SECFailure; 1.225 +} 1.226 + 1.227 +#define INDENT_MULT 4 1.228 +void 1.229 +SECU_Indent(FILE *out, int level) 1.230 +{ 1.231 + int i; 1.232 + 1.233 + for (i = 0; i < level; i++) { 1.234 + fprintf(out, " "); 1.235 + } 1.236 +} 1.237 + 1.238 +void SECU_Newline(FILE *out) 1.239 +{ 1.240 + fprintf(out, "\n"); 1.241 +} 1.242 + 1.243 +void 1.244 +SECU_PrintAsHex(FILE *out, const SECItem *data, const char *m, int level) 1.245 +{ 1.246 + unsigned i; 1.247 + int column; 1.248 + PRBool isString = PR_TRUE; 1.249 + PRBool isWhiteSpace = PR_TRUE; 1.250 + PRBool printedHex = PR_FALSE; 1.251 + unsigned int limit = 15; 1.252 + 1.253 + if ( m ) { 1.254 + SECU_Indent(out, level); fprintf(out, "%s:", m); 1.255 + level++; 1.256 + if (wrapEnabled) 1.257 + fprintf(out, "\n"); 1.258 + } 1.259 + 1.260 + if (wrapEnabled) { 1.261 + SECU_Indent(out, level); column = level*INDENT_MULT; 1.262 + } 1.263 + if (!data->len) { 1.264 + fprintf(out, "(empty)\n"); 1.265 + return; 1.266 + } 1.267 + /* take a pass to see if it's all printable. */ 1.268 + for (i = 0; i < data->len; i++) { 1.269 + unsigned char val = data->data[i]; 1.270 + if (!val || !isprint(val)) { 1.271 + isString = PR_FALSE; 1.272 + break; 1.273 + } 1.274 + if (isWhiteSpace && !isspace(val)) { 1.275 + isWhiteSpace = PR_FALSE; 1.276 + } 1.277 + } 1.278 + 1.279 + /* Short values, such as bit strings (which are printed with this 1.280 + ** function) often look like strings, but we want to see the bits. 1.281 + ** so this test assures that short values will be printed in hex, 1.282 + ** perhaps in addition to being printed as strings. 1.283 + ** The threshold size (4 bytes) is arbitrary. 1.284 + */ 1.285 + if (!isString || data->len <= 4) { 1.286 + for (i = 0; i < data->len; i++) { 1.287 + if (i != data->len - 1) { 1.288 + fprintf(out, "%02x:", data->data[i]); 1.289 + column += 3; 1.290 + } else { 1.291 + fprintf(out, "%02x", data->data[i]); 1.292 + column += 2; 1.293 + break; 1.294 + } 1.295 + if (wrapEnabled && 1.296 + (column > 76 || (i % 16 == limit))) { 1.297 + SECU_Newline(out); 1.298 + SECU_Indent(out, level); 1.299 + column = level*INDENT_MULT; 1.300 + limit = i % 16; 1.301 + } 1.302 + } 1.303 + printedHex = PR_TRUE; 1.304 + } 1.305 + if (isString && !isWhiteSpace) { 1.306 + if (printedHex != PR_FALSE) { 1.307 + SECU_Newline(out); 1.308 + SECU_Indent(out, level); column = level*INDENT_MULT; 1.309 + } 1.310 + for (i = 0; i < data->len; i++) { 1.311 + unsigned char val = data->data[i]; 1.312 + 1.313 + if (val) { 1.314 + fprintf(out,"%c",val); 1.315 + column++; 1.316 + } else { 1.317 + column = 77; 1.318 + } 1.319 + if (wrapEnabled && column > 76) { 1.320 + SECU_Newline(out); 1.321 + SECU_Indent(out, level); column = level*INDENT_MULT; 1.322 + } 1.323 + } 1.324 + } 1.325 + 1.326 + if (column != level*INDENT_MULT) { 1.327 + SECU_Newline(out); 1.328 + } 1.329 +} 1.330 + 1.331 +const char *hex = "0123456789abcdef"; 1.332 + 1.333 +const char printable[257] = { 1.334 + "................" /* 0x */ 1.335 + "................" /* 1x */ 1.336 + " !\"#$%&'()*+,-./" /* 2x */ 1.337 + "0123456789:;<=>?" /* 3x */ 1.338 + "@ABCDEFGHIJKLMNO" /* 4x */ 1.339 + "PQRSTUVWXYZ[\\]^_" /* 5x */ 1.340 + "`abcdefghijklmno" /* 6x */ 1.341 + "pqrstuvwxyz{|}~." /* 7x */ 1.342 + "................" /* 8x */ 1.343 + "................" /* 9x */ 1.344 + "................" /* ax */ 1.345 + "................" /* bx */ 1.346 + "................" /* cx */ 1.347 + "................" /* dx */ 1.348 + "................" /* ex */ 1.349 + "................" /* fx */ 1.350 +}; 1.351 + 1.352 +void 1.353 +SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len) 1.354 +{ 1.355 + const unsigned char *cp = (const unsigned char *)vp; 1.356 + char buf[80]; 1.357 + char *bp; 1.358 + char *ap; 1.359 + 1.360 + fprintf(out, "%s [Len: %d]\n", msg, len); 1.361 + memset(buf, ' ', sizeof buf); 1.362 + bp = buf; 1.363 + ap = buf + 50; 1.364 + while (--len >= 0) { 1.365 + unsigned char ch = *cp++; 1.366 + *bp++ = hex[(ch >> 4) & 0xf]; 1.367 + *bp++ = hex[ch & 0xf]; 1.368 + *bp++ = ' '; 1.369 + *ap++ = printable[ch]; 1.370 + if (ap - buf >= 66) { 1.371 + *ap = 0; 1.372 + fprintf(out, " %s\n", buf); 1.373 + memset(buf, ' ', sizeof buf); 1.374 + bp = buf; 1.375 + ap = buf + 50; 1.376 + } 1.377 + } 1.378 + if (bp > buf) { 1.379 + *ap = 0; 1.380 + fprintf(out, " %s\n", buf); 1.381 + } 1.382 +} 1.383 + 1.384 + 1.385 +/* This expents i->data[0] to be the MSB of the integer. 1.386 +** if you want to print a DER-encoded integer (with the tag and length) 1.387 +** call SECU_PrintEncodedInteger(); 1.388 +*/ 1.389 +void 1.390 +SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, int level) 1.391 +{ 1.392 + int iv; 1.393 + 1.394 + if (!i || !i->len || !i->data) { 1.395 + SECU_Indent(out, level); 1.396 + if (m) { 1.397 + fprintf(out, "%s: (null)\n", m); 1.398 + } else { 1.399 + fprintf(out, "(null)\n"); 1.400 + } 1.401 + } else if (i->len > 4) { 1.402 + SECU_PrintAsHex(out, i, m, level); 1.403 + } else { 1.404 + if (i->type == siUnsignedInteger && *i->data & 0x80) { 1.405 + /* Make sure i->data has zero in the highest bite 1.406 + * if i->data is an unsigned integer */ 1.407 + SECItem tmpI; 1.408 + char data[] = {0, 0, 0, 0, 0}; 1.409 + 1.410 + PORT_Memcpy(data + 1, i->data, i->len); 1.411 + tmpI.len = i->len + 1; 1.412 + tmpI.data = (void*)data; 1.413 + 1.414 + iv = DER_GetInteger(&tmpI); 1.415 + } else { 1.416 + iv = DER_GetInteger(i); 1.417 + } 1.418 + SECU_Indent(out, level); 1.419 + if (m) { 1.420 + fprintf(out, "%s: %d (0x%x)\n", m, iv, iv); 1.421 + } else { 1.422 + fprintf(out, "%d (0x%x)\n", iv, iv); 1.423 + } 1.424 + } 1.425 +} 1.426 + 1.427 +#if defined(DEBUG) || defined(FORCE_PR_ASSERT) 1.428 +/* Returns true iff a[i].flag has a duplicate in a[i+1 : count-1] */ 1.429 +static PRBool HasShortDuplicate(int i, secuCommandFlag *a, int count) 1.430 +{ 1.431 + char target = a[i].flag; 1.432 + int j; 1.433 + 1.434 + /* duplicate '\0' flags are okay, they are used with long forms */ 1.435 + for (j = i+1; j < count; j++) { 1.436 + if (a[j].flag && a[j].flag == target) { 1.437 + return PR_TRUE; 1.438 + } 1.439 + } 1.440 + return PR_FALSE; 1.441 +} 1.442 + 1.443 +/* Returns true iff a[i].longform has a duplicate in a[i+1 : count-1] */ 1.444 +static PRBool HasLongDuplicate(int i, secuCommandFlag *a, int count) 1.445 +{ 1.446 + int j; 1.447 + char *target = a[i].longform; 1.448 + 1.449 + if (!target) 1.450 + return PR_FALSE; 1.451 + 1.452 + for (j = i+1; j < count; j++) { 1.453 + if (a[j].longform && strcmp(a[j].longform, target) == 0) { 1.454 + return PR_TRUE; 1.455 + } 1.456 + } 1.457 + return PR_FALSE; 1.458 +} 1.459 + 1.460 +/* Returns true iff a has no short or long form duplicates 1.461 + */ 1.462 +PRBool HasNoDuplicates(secuCommandFlag *a, int count) 1.463 +{ 1.464 + int i; 1.465 + 1.466 + for (i = 0; i < count; i++) { 1.467 + if (a[i].flag && HasShortDuplicate(i, a, count)) { 1.468 + return PR_FALSE; 1.469 + } 1.470 + if (a[i].longform && HasLongDuplicate(i, a, count)) { 1.471 + return PR_FALSE; 1.472 + } 1.473 + } 1.474 + return PR_TRUE; 1.475 +} 1.476 +#endif 1.477 + 1.478 +SECStatus 1.479 +SECU_ParseCommandLine(int argc, char **argv, char *progName, 1.480 + const secuCommand *cmd) 1.481 +{ 1.482 + PRBool found; 1.483 + PLOptState *optstate; 1.484 + PLOptStatus status; 1.485 + char *optstring; 1.486 + PLLongOpt *longopts = NULL; 1.487 + int i, j; 1.488 + int lcmd = 0, lopt = 0; 1.489 + 1.490 + PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands)); 1.491 + PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions)); 1.492 + 1.493 + optstring = (char *)PORT_Alloc(cmd->numCommands + 2*cmd->numOptions+1); 1.494 + if (optstring == NULL) 1.495 + return SECFailure; 1.496 + 1.497 + j = 0; 1.498 + for (i=0; i<cmd->numCommands; i++) { 1.499 + if (cmd->commands[i].flag) /* single character option ? */ 1.500 + optstring[j++] = cmd->commands[i].flag; 1.501 + if (cmd->commands[i].longform) 1.502 + lcmd++; 1.503 + } 1.504 + for (i=0; i<cmd->numOptions; i++) { 1.505 + if (cmd->options[i].flag) { 1.506 + optstring[j++] = cmd->options[i].flag; 1.507 + if (cmd->options[i].needsArg) 1.508 + optstring[j++] = ':'; 1.509 + } 1.510 + if (cmd->options[i].longform) 1.511 + lopt++; 1.512 + } 1.513 + 1.514 + optstring[j] = '\0'; 1.515 + 1.516 + if (lcmd + lopt > 0) { 1.517 + longopts = PORT_NewArray(PLLongOpt, lcmd+lopt+1); 1.518 + if (!longopts) { 1.519 + PORT_Free(optstring); 1.520 + return SECFailure; 1.521 + } 1.522 + 1.523 + j = 0; 1.524 + for (i=0; j<lcmd && i<cmd->numCommands; i++) { 1.525 + if (cmd->commands[i].longform) { 1.526 + longopts[j].longOptName = cmd->commands[i].longform; 1.527 + longopts[j].longOption = 0; 1.528 + longopts[j++].valueRequired = cmd->commands[i].needsArg; 1.529 + } 1.530 + } 1.531 + lopt += lcmd; 1.532 + for (i=0; j<lopt && i<cmd->numOptions; i++) { 1.533 + if (cmd->options[i].longform) { 1.534 + longopts[j].longOptName = cmd->options[i].longform; 1.535 + longopts[j].longOption = 0; 1.536 + longopts[j++].valueRequired = cmd->options[i].needsArg; 1.537 + } 1.538 + } 1.539 + longopts[j].longOptName = NULL; 1.540 + } 1.541 + 1.542 + optstate = PL_CreateLongOptState(argc, argv, optstring, longopts); 1.543 + if (!optstate) { 1.544 + PORT_Free(optstring); 1.545 + PORT_Free(longopts); 1.546 + return SECFailure; 1.547 + } 1.548 + /* Parse command line arguments */ 1.549 + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.550 + const char *optstatelong; 1.551 + char option = optstate->option; 1.552 + 1.553 + /* positional parameter, single-char option or long opt? */ 1.554 + if (optstate->longOptIndex == -1) { 1.555 + /* not a long opt */ 1.556 + if (option == '\0') 1.557 + continue; /* it's a positional parameter */ 1.558 + optstatelong = ""; 1.559 + } else { 1.560 + /* long opt */ 1.561 + if (option == '\0') 1.562 + option = '\377'; /* force unequal with all flags */ 1.563 + optstatelong = longopts[optstate->longOptIndex].longOptName; 1.564 + } 1.565 + 1.566 + found = PR_FALSE; 1.567 + 1.568 + for (i=0; i<cmd->numCommands; i++) { 1.569 + if (cmd->commands[i].flag == option || 1.570 + cmd->commands[i].longform == optstatelong) { 1.571 + cmd->commands[i].activated = PR_TRUE; 1.572 + if (optstate->value) { 1.573 + cmd->commands[i].arg = (char *)optstate->value; 1.574 + } 1.575 + found = PR_TRUE; 1.576 + break; 1.577 + } 1.578 + } 1.579 + 1.580 + if (found) 1.581 + continue; 1.582 + 1.583 + for (i=0; i<cmd->numOptions; i++) { 1.584 + if (cmd->options[i].flag == option || 1.585 + cmd->options[i].longform == optstatelong) { 1.586 + cmd->options[i].activated = PR_TRUE; 1.587 + if (optstate->value) { 1.588 + cmd->options[i].arg = (char *)optstate->value; 1.589 + } else if (cmd->options[i].needsArg) { 1.590 + status = PL_OPT_BAD; 1.591 + goto loser; 1.592 + } 1.593 + found = PR_TRUE; 1.594 + break; 1.595 + } 1.596 + } 1.597 + 1.598 + if (!found) { 1.599 + status = PL_OPT_BAD; 1.600 + break; 1.601 + } 1.602 + } 1.603 + 1.604 +loser: 1.605 + PL_DestroyOptState(optstate); 1.606 + PORT_Free(optstring); 1.607 + if (longopts) 1.608 + PORT_Free(longopts); 1.609 + if (status == PL_OPT_BAD) 1.610 + return SECFailure; 1.611 + return SECSuccess; 1.612 +} 1.613 + 1.614 +char * 1.615 +SECU_GetOptionArg(const secuCommand *cmd, int optionNum) 1.616 +{ 1.617 + if (optionNum < 0 || optionNum >= cmd->numOptions) 1.618 + return NULL; 1.619 + if (cmd->options[optionNum].activated) 1.620 + return PL_strdup(cmd->options[optionNum].arg); 1.621 + else 1.622 + return NULL; 1.623 +} 1.624 + 1.625 + 1.626 +void 1.627 +SECU_PrintPRandOSError(const char *progName) 1.628 +{ 1.629 + char buffer[513]; 1.630 + PRInt32 errLen = PR_GetErrorTextLength(); 1.631 + if (errLen > 0 && errLen < sizeof buffer) { 1.632 + PR_GetErrorText(buffer); 1.633 + } 1.634 + SECU_PrintError(progName, "function failed"); 1.635 + if (errLen > 0 && errLen < sizeof buffer) { 1.636 + PR_fprintf(PR_STDERR, "\t%s\n", buffer); 1.637 + } 1.638 +} 1.639 + 1.640 +SECOidTag 1.641 +SECU_StringToSignatureAlgTag(const char *alg) 1.642 +{ 1.643 + SECOidTag hashAlgTag = SEC_OID_UNKNOWN; 1.644 + 1.645 + if (alg) { 1.646 + if (!PL_strcmp(alg, "MD2")) { 1.647 + hashAlgTag = SEC_OID_MD2; 1.648 + } else if (!PL_strcmp(alg, "MD4")) { 1.649 + hashAlgTag = SEC_OID_MD4; 1.650 + } else if (!PL_strcmp(alg, "MD5")) { 1.651 + hashAlgTag = SEC_OID_MD5; 1.652 + } else if (!PL_strcmp(alg, "SHA1")) { 1.653 + hashAlgTag = SEC_OID_SHA1; 1.654 + } else if (!PL_strcmp(alg, "SHA224")) { 1.655 + hashAlgTag = SEC_OID_SHA224; 1.656 + } else if (!PL_strcmp(alg, "SHA256")) { 1.657 + hashAlgTag = SEC_OID_SHA256; 1.658 + } else if (!PL_strcmp(alg, "SHA384")) { 1.659 + hashAlgTag = SEC_OID_SHA384; 1.660 + } else if (!PL_strcmp(alg, "SHA512")) { 1.661 + hashAlgTag = SEC_OID_SHA512; 1.662 + } 1.663 + } 1.664 + return hashAlgTag; 1.665 +} 1.666 + 1.667 +/* Caller ensures that dst is at least item->len*2+1 bytes long */ 1.668 +void 1.669 +SECU_SECItemToHex(const SECItem * item, char * dst) 1.670 +{ 1.671 + if (dst && item && item->data) { 1.672 + unsigned char * src = item->data; 1.673 + unsigned int len = item->len; 1.674 + for (; len > 0; --len, dst += 2) { 1.675 + sprintf(dst, "%02x", *src++); 1.676 + } 1.677 + *dst = '\0'; 1.678 + } 1.679 +} 1.680 + 1.681 +static unsigned char nibble(char c) { 1.682 + c = PORT_Tolower(c); 1.683 + return ( c >= '0' && c <= '9') ? c - '0' : 1.684 + ( c >= 'a' && c <= 'f') ? c - 'a' +10 : -1; 1.685 +} 1.686 + 1.687 +SECStatus 1.688 +SECU_SECItemHexStringToBinary(SECItem* srcdest) 1.689 +{ 1.690 + int i; 1.691 + 1.692 + if (!srcdest) { 1.693 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.694 + return SECFailure; 1.695 + } 1.696 + if (srcdest->len < 4 || (srcdest->len % 2) ) { 1.697 + /* too short to convert, or even number of characters */ 1.698 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.699 + return SECFailure; 1.700 + } 1.701 + if (PORT_Strncasecmp((const char*)srcdest->data, "0x", 2)) { 1.702 + /* wrong prefix */ 1.703 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.704 + return SECFailure; 1.705 + } 1.706 + 1.707 + /* 1st pass to check for hex characters */ 1.708 + for (i=2; i<srcdest->len; i++) { 1.709 + char c = PORT_Tolower(srcdest->data[i]); 1.710 + if (! ( ( c >= '0' && c <= '9') || 1.711 + ( c >= 'a' && c <= 'f') 1.712 + ) ) { 1.713 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.714 + return SECFailure; 1.715 + } 1.716 + } 1.717 + 1.718 + /* 2nd pass to convert */ 1.719 + for (i=2; i<srcdest->len; i+=2) { 1.720 + srcdest->data[(i-2)/2] = (nibble(srcdest->data[i]) << 4) + 1.721 + nibble(srcdest->data[i+1]); 1.722 + } 1.723 + 1.724 + /* adjust length */ 1.725 + srcdest->len -= 2; 1.726 + srcdest->len /= 2; 1.727 + return SECSuccess; 1.728 +}