PageRenderTime 69ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/cmd/lib/secutil.c

https://bitbucket.org/mkato/mozilla-1.9.0-win64
C | 4116 lines | 3360 code | 513 blank | 243 comment | 866 complexity | 560e1bd79c68f204d7f7158f868c5ea2 MD5 | raw file
Possible License(s): LGPL-3.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /*
  38. ** secutil.c - various functions used by security stuff
  39. **
  40. */
  41. #include "prtypes.h"
  42. #include "prtime.h"
  43. #include "prlong.h"
  44. #include "prerror.h"
  45. #include "prprf.h"
  46. #include "plgetopt.h"
  47. #include "prenv.h"
  48. #include "prnetdb.h"
  49. #include "cryptohi.h"
  50. #include "secutil.h"
  51. #include "secpkcs7.h"
  52. #include "secpkcs5.h"
  53. #include <stdarg.h>
  54. #if !defined(_WIN32_WCE)
  55. #include <sys/stat.h>
  56. #include <errno.h>
  57. #endif
  58. #ifdef XP_UNIX
  59. #include <unistd.h>
  60. #endif
  61. /* for SEC_TraverseNames */
  62. #include "cert.h"
  63. #include "certt.h"
  64. #include "certdb.h"
  65. /* #include "secmod.h" */
  66. #include "pk11func.h"
  67. #include "secoid.h"
  68. static char consoleName[] = {
  69. #ifdef XP_UNIX
  70. #ifdef VMS
  71. "TT"
  72. #else
  73. "/dev/tty"
  74. #endif
  75. #else
  76. #ifdef XP_OS2
  77. "\\DEV\\CON"
  78. #else
  79. "CON:"
  80. #endif
  81. #endif
  82. };
  83. char *
  84. SECU_GetString(int16 error_number)
  85. {
  86. static char errString[80];
  87. sprintf(errString, "Unknown error string (%d)", error_number);
  88. return errString;
  89. }
  90. void
  91. SECU_PrintErrMsg(FILE *out, int level, char *progName, char *msg, ...)
  92. {
  93. va_list args;
  94. PRErrorCode err = PORT_GetError();
  95. const char * errString = SECU_Strerror(err);
  96. va_start(args, msg);
  97. SECU_Indent(out, level);
  98. fprintf(out, "%s: ", progName);
  99. vfprintf(out, msg, args);
  100. if (errString != NULL && PORT_Strlen(errString) > 0)
  101. fprintf(out, ": %s\n", errString);
  102. else
  103. fprintf(out, ": error %d\n", (int)err);
  104. va_end(args);
  105. }
  106. void
  107. SECU_PrintError(char *progName, char *msg, ...)
  108. {
  109. va_list args;
  110. PRErrorCode err = PORT_GetError();
  111. const char * errString = SECU_Strerror(err);
  112. va_start(args, msg);
  113. fprintf(stderr, "%s: ", progName);
  114. vfprintf(stderr, msg, args);
  115. if (errString != NULL && PORT_Strlen(errString) > 0)
  116. fprintf(stderr, ": %s\n", errString);
  117. else
  118. fprintf(stderr, ": error %d\n", (int)err);
  119. va_end(args);
  120. }
  121. void
  122. SECU_PrintSystemError(char *progName, char *msg, ...)
  123. {
  124. va_list args;
  125. va_start(args, msg);
  126. fprintf(stderr, "%s: ", progName);
  127. vfprintf(stderr, msg, args);
  128. #if defined(_WIN32_WCE)
  129. fprintf(stderr, ": %d\n", PR_GetOSError());
  130. #else
  131. fprintf(stderr, ": %s\n", strerror(errno));
  132. #endif
  133. va_end(args);
  134. }
  135. static void
  136. secu_ClearPassword(char *p)
  137. {
  138. if (p) {
  139. PORT_Memset(p, 0, PORT_Strlen(p));
  140. PORT_Free(p);
  141. }
  142. }
  143. char *
  144. SECU_GetPasswordString(void *arg, char *prompt)
  145. {
  146. #ifndef _WINDOWS
  147. char *p = NULL;
  148. FILE *input, *output;
  149. /* open terminal */
  150. input = fopen(consoleName, "r");
  151. if (input == NULL) {
  152. fprintf(stderr, "Error opening input terminal for read\n");
  153. return NULL;
  154. }
  155. output = fopen(consoleName, "w");
  156. if (output == NULL) {
  157. fprintf(stderr, "Error opening output terminal for write\n");
  158. return NULL;
  159. }
  160. p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword);
  161. fclose(input);
  162. fclose(output);
  163. return p;
  164. #else
  165. /* Win32 version of above. opening the console may fail
  166. on windows95, and certainly isn't necessary.. */
  167. char *p = NULL;
  168. p = SEC_GetPassword (stdin, stdout, prompt, SEC_BlindCheckPassword);
  169. return p;
  170. #endif
  171. }
  172. /*
  173. * p a s s w o r d _ h a r d c o d e
  174. *
  175. * A function to use the password passed in the -f(pwfile) argument
  176. * of the command line.
  177. * After use once, null it out otherwise PKCS11 calls us forever.?
  178. *
  179. */
  180. char *
  181. SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
  182. {
  183. char* phrases, *phrase;
  184. PRFileDesc *fd;
  185. PRInt32 nb;
  186. char *pwFile = arg;
  187. int i;
  188. const long maxPwdFileSize = 4096;
  189. char* tokenName = NULL;
  190. int tokenLen = 0;
  191. if (!pwFile)
  192. return 0;
  193. if (retry) {
  194. return 0; /* no good retrying - the files contents will be the same */
  195. }
  196. phrases = PORT_ZAlloc(maxPwdFileSize);
  197. if (!phrases) {
  198. return 0; /* out of memory */
  199. }
  200. fd = PR_Open(pwFile, PR_RDONLY, 0);
  201. if (!fd) {
  202. fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
  203. PORT_Free(phrases);
  204. return NULL;
  205. }
  206. nb = PR_Read(fd, phrases, maxPwdFileSize);
  207. PR_Close(fd);
  208. if (nb == 0) {
  209. fprintf(stderr,"password file contains no data\n");
  210. PORT_Free(phrases);
  211. return NULL;
  212. }
  213. if (slot) {
  214. tokenName = PK11_GetTokenName(slot);
  215. if (tokenName) {
  216. tokenLen = PORT_Strlen(tokenName);
  217. }
  218. }
  219. i = 0;
  220. do
  221. {
  222. int startphrase = i;
  223. int phraseLen;
  224. /* handle the Windows EOL case */
  225. while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++;
  226. /* terminate passphrase */
  227. phrases[i++] = '\0';
  228. /* clean up any EOL before the start of the next passphrase */
  229. while ( (i<nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
  230. phrases[i++] = '\0';
  231. }
  232. /* now analyze the current passphrase */
  233. phrase = &phrases[startphrase];
  234. if (!tokenName)
  235. break;
  236. if (PORT_Strncmp(phrase, tokenName, tokenLen)) continue;
  237. phraseLen = PORT_Strlen(phrase);
  238. if (phraseLen < (tokenLen+1)) continue;
  239. if (phrase[tokenLen] != ':') continue;
  240. phrase = &phrase[tokenLen+1];
  241. break;
  242. } while (i<nb);
  243. phrase = PORT_Strdup((char*)phrase);
  244. PORT_Free(phrases);
  245. return phrase;
  246. }
  247. char *
  248. SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
  249. {
  250. char prompt[255];
  251. secuPWData *pwdata = (secuPWData *)arg;
  252. secuPWData pwnull = { PW_NONE, 0 };
  253. secuPWData pwxtrn = { PW_EXTERNAL, "external" };
  254. char *pw;
  255. if (pwdata == NULL)
  256. pwdata = &pwnull;
  257. if (PK11_ProtectedAuthenticationPath(slot)) {
  258. pwdata = &pwxtrn;
  259. }
  260. if (retry && pwdata->source != PW_NONE) {
  261. PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
  262. return NULL;
  263. }
  264. switch (pwdata->source) {
  265. case PW_NONE:
  266. sprintf(prompt, "Enter Password or Pin for \"%s\":",
  267. PK11_GetTokenName(slot));
  268. return SECU_GetPasswordString(NULL, prompt);
  269. case PW_FROMFILE:
  270. /* Instead of opening and closing the file every time, get the pw
  271. * once, then keep it in memory (duh).
  272. */
  273. pw = SECU_FilePasswd(slot, retry, pwdata->data);
  274. pwdata->source = PW_PLAINTEXT;
  275. pwdata->data = PL_strdup(pw);
  276. /* it's already been dup'ed */
  277. return pw;
  278. case PW_EXTERNAL:
  279. sprintf(prompt,
  280. "Press Enter, then enter PIN for \"%s\" on external device.\n",
  281. PK11_GetTokenName(slot));
  282. (void) SECU_GetPasswordString(NULL, prompt);
  283. /* Fall Through */
  284. case PW_PLAINTEXT:
  285. return PL_strdup(pwdata->data);
  286. default:
  287. break;
  288. }
  289. PR_fprintf(PR_STDERR, "Password check failed: No password found.\n");
  290. return NULL;
  291. }
  292. char *
  293. secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
  294. {
  295. char *p0 = NULL;
  296. char *p1 = NULL;
  297. FILE *input, *output;
  298. secuPWData *pwdata = arg;
  299. if (pwdata->source == PW_FROMFILE) {
  300. return SECU_FilePasswd(slot, retry, pwdata->data);
  301. }
  302. if (pwdata->source == PW_PLAINTEXT) {
  303. return PL_strdup(pwdata->data);
  304. }
  305. /* PW_NONE - get it from tty */
  306. /* open terminal */
  307. #ifdef _WINDOWS
  308. input = stdin;
  309. #else
  310. input = fopen(consoleName, "r");
  311. #endif
  312. if (input == NULL) {
  313. PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
  314. return NULL;
  315. }
  316. /* we have no password, so initialize database with one */
  317. PR_fprintf(PR_STDERR,
  318. "Enter a password which will be used to encrypt your keys.\n"
  319. "The password should be at least 8 characters long,\n"
  320. "and should contain at least one non-alphabetic character.\n\n");
  321. output = fopen(consoleName, "w");
  322. if (output == NULL) {
  323. PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
  324. return NULL;
  325. }
  326. for (;;) {
  327. if (p0)
  328. PORT_Free(p0);
  329. p0 = SEC_GetPassword(input, output, "Enter new password: ",
  330. SEC_BlindCheckPassword);
  331. if (p1)
  332. PORT_Free(p1);
  333. p1 = SEC_GetPassword(input, output, "Re-enter password: ",
  334. SEC_BlindCheckPassword);
  335. if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
  336. break;
  337. }
  338. PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
  339. }
  340. /* clear out the duplicate password string */
  341. secu_ClearPassword(p1);
  342. fclose(input);
  343. fclose(output);
  344. return p0;
  345. }
  346. SECStatus
  347. SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
  348. {
  349. return SECU_ChangePW2(slot, passwd, 0, pwFile, 0);
  350. }
  351. SECStatus
  352. SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
  353. char *oldPwFile, char *newPwFile)
  354. {
  355. SECStatus rv;
  356. secuPWData pwdata, newpwdata;
  357. char *oldpw = NULL, *newpw = NULL;
  358. if (oldPass) {
  359. pwdata.source = PW_PLAINTEXT;
  360. pwdata.data = oldPass;
  361. } else if (oldPwFile) {
  362. pwdata.source = PW_FROMFILE;
  363. pwdata.data = oldPwFile;
  364. } else {
  365. pwdata.source = PW_NONE;
  366. pwdata.data = NULL;
  367. }
  368. if (newPass) {
  369. newpwdata.source = PW_PLAINTEXT;
  370. newpwdata.data = newPass;
  371. } else if (newPwFile) {
  372. newpwdata.source = PW_FROMFILE;
  373. newpwdata.data = newPwFile;
  374. } else {
  375. newpwdata.source = PW_NONE;
  376. newpwdata.data = NULL;
  377. }
  378. if (PK11_NeedUserInit(slot)) {
  379. newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata);
  380. rv = PK11_InitPin(slot, (char*)NULL, newpw);
  381. goto done;
  382. }
  383. for (;;) {
  384. oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata);
  385. if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
  386. if (pwdata.source == PW_NONE) {
  387. PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
  388. } else {
  389. PR_fprintf(PR_STDERR, "Invalid password.\n");
  390. PORT_Memset(oldpw, 0, PL_strlen(oldpw));
  391. PORT_Free(oldpw);
  392. return SECFailure;
  393. }
  394. } else
  395. break;
  396. PORT_Free(oldpw);
  397. }
  398. newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
  399. if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
  400. PR_fprintf(PR_STDERR, "Failed to change password.\n");
  401. return SECFailure;
  402. }
  403. PORT_Memset(oldpw, 0, PL_strlen(oldpw));
  404. PORT_Free(oldpw);
  405. PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
  406. done:
  407. PORT_Memset(newpw, 0, PL_strlen(newpw));
  408. PORT_Free(newpw);
  409. return SECSuccess;
  410. }
  411. struct matchobj {
  412. SECItem index;
  413. char *nname;
  414. PRBool found;
  415. };
  416. char *
  417. SECU_DefaultSSLDir(void)
  418. {
  419. char *dir;
  420. static char sslDir[1000];
  421. dir = PR_GetEnv("SSL_DIR");
  422. if (!dir)
  423. return NULL;
  424. sprintf(sslDir, "%s", dir);
  425. if (sslDir[strlen(sslDir)-1] == '/')
  426. sslDir[strlen(sslDir)-1] = 0;
  427. return sslDir;
  428. }
  429. char *
  430. SECU_AppendFilenameToDir(char *dir, char *filename)
  431. {
  432. static char path[1000];
  433. if (dir[strlen(dir)-1] == '/')
  434. sprintf(path, "%s%s", dir, filename);
  435. else
  436. sprintf(path, "%s/%s", dir, filename);
  437. return path;
  438. }
  439. char *
  440. SECU_ConfigDirectory(const char* base)
  441. {
  442. static PRBool initted = PR_FALSE;
  443. const char *dir = ".netscape";
  444. char *home;
  445. static char buf[1000];
  446. if (initted) return buf;
  447. if (base == NULL || *base == 0) {
  448. home = PR_GetEnv("HOME");
  449. if (!home) home = "";
  450. if (*home && home[strlen(home) - 1] == '/')
  451. sprintf (buf, "%.900s%s", home, dir);
  452. else
  453. sprintf (buf, "%.900s/%s", home, dir);
  454. } else {
  455. sprintf(buf, "%.900s", base);
  456. if (buf[strlen(buf) - 1] == '/')
  457. buf[strlen(buf) - 1] = 0;
  458. }
  459. initted = PR_TRUE;
  460. return buf;
  461. }
  462. /*Turn off SSL for now */
  463. /* This gets called by SSL when server wants our cert & key */
  464. int
  465. SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
  466. struct CERTDistNamesStr *caNames,
  467. struct CERTCertificateStr **pRetCert,
  468. struct SECKEYPrivateKeyStr **pRetKey)
  469. {
  470. SECKEYPrivateKey *key;
  471. CERTCertificate *cert;
  472. int errsave;
  473. if (arg == NULL) {
  474. fprintf(stderr, "no key/cert name specified for client auth\n");
  475. return -1;
  476. }
  477. cert = PK11_FindCertFromNickname(arg, NULL);
  478. errsave = PORT_GetError();
  479. if (!cert) {
  480. if (errsave == SEC_ERROR_BAD_PASSWORD)
  481. fprintf(stderr, "Bad password\n");
  482. else if (errsave > 0)
  483. fprintf(stderr, "Unable to read cert (error %d)\n", errsave);
  484. else if (errsave == SEC_ERROR_BAD_DATABASE)
  485. fprintf(stderr, "Unable to get cert from database (%d)\n", errsave);
  486. else
  487. fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave);
  488. return -1;
  489. }
  490. key = PK11_FindKeyByAnyCert(arg,NULL);
  491. if (!key) {
  492. fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError());
  493. return -1;
  494. }
  495. *pRetCert = cert;
  496. *pRetKey = key;
  497. return 0;
  498. }
  499. SECStatus
  500. secu_StdinToItem(SECItem *dst)
  501. {
  502. unsigned char buf[1000];
  503. PRInt32 numBytes;
  504. PRBool notDone = PR_TRUE;
  505. dst->len = 0;
  506. dst->data = NULL;
  507. while (notDone) {
  508. numBytes = PR_Read(PR_STDIN, buf, sizeof(buf));
  509. if (numBytes < 0) {
  510. return SECFailure;
  511. }
  512. if (numBytes == 0)
  513. break;
  514. if (dst->data) {
  515. unsigned char * p = dst->data;
  516. dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes);
  517. if (!dst->data) {
  518. PORT_Free(p);
  519. }
  520. } else {
  521. dst->data = (unsigned char*)PORT_Alloc(numBytes);
  522. }
  523. if (!dst->data) {
  524. return SECFailure;
  525. }
  526. PORT_Memcpy(dst->data + dst->len, buf, numBytes);
  527. dst->len += numBytes;
  528. }
  529. return SECSuccess;
  530. }
  531. SECStatus
  532. SECU_FileToItem(SECItem *dst, PRFileDesc *src)
  533. {
  534. PRFileInfo info;
  535. PRInt32 numBytes;
  536. PRStatus prStatus;
  537. if (src == PR_STDIN)
  538. return secu_StdinToItem(dst);
  539. prStatus = PR_GetOpenFileInfo(src, &info);
  540. if (prStatus != PR_SUCCESS) {
  541. PORT_SetError(SEC_ERROR_IO);
  542. return SECFailure;
  543. }
  544. /* XXX workaround for 3.1, not all utils zero dst before sending */
  545. dst->data = 0;
  546. if (!SECITEM_AllocItem(NULL, dst, info.size))
  547. goto loser;
  548. numBytes = PR_Read(src, dst->data, info.size);
  549. if (numBytes != info.size) {
  550. PORT_SetError(SEC_ERROR_IO);
  551. goto loser;
  552. }
  553. return SECSuccess;
  554. loser:
  555. SECITEM_FreeItem(dst, PR_FALSE);
  556. dst->data = NULL;
  557. return SECFailure;
  558. }
  559. SECStatus
  560. SECU_TextFileToItem(SECItem *dst, PRFileDesc *src)
  561. {
  562. PRFileInfo info;
  563. PRInt32 numBytes;
  564. PRStatus prStatus;
  565. unsigned char *buf;
  566. if (src == PR_STDIN)
  567. return secu_StdinToItem(dst);
  568. prStatus = PR_GetOpenFileInfo(src, &info);
  569. if (prStatus != PR_SUCCESS) {
  570. PORT_SetError(SEC_ERROR_IO);
  571. return SECFailure;
  572. }
  573. buf = (unsigned char*)PORT_Alloc(info.size);
  574. if (!buf)
  575. return SECFailure;
  576. numBytes = PR_Read(src, buf, info.size);
  577. if (numBytes != info.size) {
  578. PORT_SetError(SEC_ERROR_IO);
  579. goto loser;
  580. }
  581. if (buf[numBytes-1] == '\n') numBytes--;
  582. #ifdef _WINDOWS
  583. if (buf[numBytes-1] == '\r') numBytes--;
  584. #endif
  585. /* XXX workaround for 3.1, not all utils zero dst before sending */
  586. dst->data = 0;
  587. if (!SECITEM_AllocItem(NULL, dst, numBytes))
  588. goto loser;
  589. memcpy(dst->data, buf, numBytes);
  590. PORT_Free(buf);
  591. return SECSuccess;
  592. loser:
  593. PORT_Free(buf);
  594. return SECFailure;
  595. }
  596. SECStatus
  597. SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
  598. {
  599. SECStatus rv;
  600. if (ascii) {
  601. /* First convert ascii to binary */
  602. SECItem filedata;
  603. char *asc, *body;
  604. /* Read in ascii data */
  605. rv = SECU_FileToItem(&filedata, inFile);
  606. asc = (char *)filedata.data;
  607. if (!asc) {
  608. fprintf(stderr, "unable to read data from input file\n");
  609. return SECFailure;
  610. }
  611. /* check for headers and trailers and remove them */
  612. if ((body = strstr(asc, "-----BEGIN")) != NULL) {
  613. char *trailer = NULL;
  614. asc = body;
  615. body = PORT_Strchr(body, '\n');
  616. if (!body)
  617. body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
  618. if (body)
  619. trailer = strstr(++body, "-----END");
  620. if (trailer != NULL) {
  621. *trailer = '\0';
  622. } else {
  623. fprintf(stderr, "input has header but no trailer\n");
  624. PORT_Free(filedata.data);
  625. return SECFailure;
  626. }
  627. } else {
  628. body = asc;
  629. }
  630. /* Convert to binary */
  631. rv = ATOB_ConvertAsciiToItem(der, body);
  632. if (rv) {
  633. fprintf(stderr, "error converting ascii to binary (%s)\n",
  634. SECU_Strerror(PORT_GetError()));
  635. PORT_Free(filedata.data);
  636. return SECFailure;
  637. }
  638. PORT_Free(filedata.data);
  639. } else {
  640. /* Read in binary der */
  641. rv = SECU_FileToItem(der, inFile);
  642. if (rv) {
  643. fprintf(stderr, "error converting der (%s)\n",
  644. SECU_Strerror(PORT_GetError()));
  645. return SECFailure;
  646. }
  647. }
  648. return SECSuccess;
  649. }
  650. #define INDENT_MULT 4
  651. void
  652. SECU_Indent(FILE *out, int level)
  653. {
  654. int i;
  655. for (i = 0; i < level; i++) {
  656. fprintf(out, " ");
  657. }
  658. }
  659. static void secu_Newline(FILE *out)
  660. {
  661. fprintf(out, "\n");
  662. }
  663. void
  664. SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
  665. {
  666. unsigned i;
  667. int column;
  668. PRBool isString = PR_TRUE;
  669. PRBool isWhiteSpace = PR_TRUE;
  670. PRBool printedHex = PR_FALSE;
  671. unsigned int limit = 15;
  672. if ( m ) {
  673. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  674. level++;
  675. }
  676. SECU_Indent(out, level); column = level*INDENT_MULT;
  677. if (!data->len) {
  678. fprintf(out, "(empty)\n");
  679. return;
  680. }
  681. /* take a pass to see if it's all printable. */
  682. for (i = 0; i < data->len; i++) {
  683. unsigned char val = data->data[i];
  684. if (!val || !isprint(val)) {
  685. isString = PR_FALSE;
  686. break;
  687. }
  688. if (isWhiteSpace && !isspace(val)) {
  689. isWhiteSpace = PR_FALSE;
  690. }
  691. }
  692. /* Short values, such as bit strings (which are printed with this
  693. ** function) often look like strings, but we want to see the bits.
  694. ** so this test assures that short values will be printed in hex,
  695. ** perhaps in addition to being printed as strings.
  696. ** The threshold size (4 bytes) is arbitrary.
  697. */
  698. if (!isString || data->len <= 4) {
  699. for (i = 0; i < data->len; i++) {
  700. if (i != data->len - 1) {
  701. fprintf(out, "%02x:", data->data[i]);
  702. column += 3;
  703. } else {
  704. fprintf(out, "%02x", data->data[i]);
  705. column += 2;
  706. break;
  707. }
  708. if (column > 76 || (i % 16 == limit)) {
  709. secu_Newline(out);
  710. SECU_Indent(out, level);
  711. column = level*INDENT_MULT;
  712. limit = i % 16;
  713. }
  714. }
  715. printedHex = PR_TRUE;
  716. }
  717. if (isString && !isWhiteSpace) {
  718. if (printedHex != PR_FALSE) {
  719. secu_Newline(out);
  720. SECU_Indent(out, level); column = level*INDENT_MULT;
  721. }
  722. for (i = 0; i < data->len; i++) {
  723. unsigned char val = data->data[i];
  724. if (val) {
  725. fprintf(out,"%c",val);
  726. column++;
  727. } else {
  728. column = 77;
  729. }
  730. if (column > 76) {
  731. secu_Newline(out);
  732. SECU_Indent(out, level); column = level*INDENT_MULT;
  733. }
  734. }
  735. }
  736. if (column != level*INDENT_MULT) {
  737. secu_Newline(out);
  738. }
  739. }
  740. static const char *hex = "0123456789abcdef";
  741. static const char printable[257] = {
  742. "................" /* 0x */
  743. "................" /* 1x */
  744. " !\"#$%&'()*+,-./" /* 2x */
  745. "0123456789:;<=>?" /* 3x */
  746. "@ABCDEFGHIJKLMNO" /* 4x */
  747. "PQRSTUVWXYZ[\\]^_" /* 5x */
  748. "`abcdefghijklmno" /* 6x */
  749. "pqrstuvwxyz{|}~." /* 7x */
  750. "................" /* 8x */
  751. "................" /* 9x */
  752. "................" /* ax */
  753. "................" /* bx */
  754. "................" /* cx */
  755. "................" /* dx */
  756. "................" /* ex */
  757. "................" /* fx */
  758. };
  759. void
  760. SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
  761. {
  762. const unsigned char *cp = (const unsigned char *)vp;
  763. char buf[80];
  764. char *bp;
  765. char *ap;
  766. fprintf(out, "%s [Len: %d]\n", msg, len);
  767. memset(buf, ' ', sizeof buf);
  768. bp = buf;
  769. ap = buf + 50;
  770. while (--len >= 0) {
  771. unsigned char ch = *cp++;
  772. *bp++ = hex[(ch >> 4) & 0xf];
  773. *bp++ = hex[ch & 0xf];
  774. *bp++ = ' ';
  775. *ap++ = printable[ch];
  776. if (ap - buf >= 66) {
  777. *ap = 0;
  778. fprintf(out, " %s\n", buf);
  779. memset(buf, ' ', sizeof buf);
  780. bp = buf;
  781. ap = buf + 50;
  782. }
  783. }
  784. if (bp > buf) {
  785. *ap = 0;
  786. fprintf(out, " %s\n", buf);
  787. }
  788. }
  789. SECStatus
  790. SECU_StripTagAndLength(SECItem *i)
  791. {
  792. unsigned int start;
  793. if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
  794. return SECFailure;
  795. }
  796. start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
  797. if (i->len < start) {
  798. return SECFailure;
  799. }
  800. i->data += start;
  801. i->len -= start;
  802. return SECSuccess;
  803. }
  804. /* This expents i->data[0] to be the MSB of the integer.
  805. ** if you want to print a DER-encoded integer (with the tag and length)
  806. ** call SECU_PrintEncodedInteger();
  807. */
  808. void
  809. SECU_PrintInteger(FILE *out, SECItem *i, char *m, int level)
  810. {
  811. int iv;
  812. if (!i || !i->len || !i->data) {
  813. SECU_Indent(out, level);
  814. if (m) {
  815. fprintf(out, "%s: (null)\n", m);
  816. } else {
  817. fprintf(out, "(null)\n");
  818. }
  819. } else if (i->len > 4) {
  820. SECU_PrintAsHex(out, i, m, level);
  821. } else {
  822. if (i->type == siUnsignedInteger && *i->data & 0x80) {
  823. /* Make sure i->data has zero in the highest bite
  824. * if i->data is an unsigned integer */
  825. SECItem tmpI;
  826. char data[] = {0, 0, 0, 0, 0};
  827. PORT_Memcpy(data + 1, i->data, i->len);
  828. tmpI.len = i->len + 1;
  829. tmpI.data = (void*)data;
  830. iv = DER_GetInteger(&tmpI);
  831. } else {
  832. iv = DER_GetInteger(i);
  833. }
  834. SECU_Indent(out, level);
  835. if (m) {
  836. fprintf(out, "%s: %d (0x%x)\n", m, iv, iv);
  837. } else {
  838. fprintf(out, "%d (0x%x)\n", iv, iv);
  839. }
  840. }
  841. }
  842. static void
  843. secu_PrintRawString(FILE *out, SECItem *si, char *m, int level)
  844. {
  845. int column;
  846. unsigned int i;
  847. if ( m ) {
  848. SECU_Indent(out, level); fprintf(out, "%s: ", m);
  849. column = (level * INDENT_MULT) + strlen(m) + 2;
  850. level++;
  851. } else {
  852. SECU_Indent(out, level);
  853. column = level*INDENT_MULT;
  854. }
  855. fprintf(out, "\""); column++;
  856. for (i = 0; i < si->len; i++) {
  857. unsigned char val = si->data[i];
  858. if (column > 76) {
  859. secu_Newline(out);
  860. SECU_Indent(out, level); column = level*INDENT_MULT;
  861. }
  862. fprintf(out,"%c", printable[val]); column++;
  863. }
  864. fprintf(out, "\""); column++;
  865. if (column != level*INDENT_MULT || column > 76) {
  866. secu_Newline(out);
  867. }
  868. }
  869. void
  870. SECU_PrintString(FILE *out, SECItem *si, char *m, int level)
  871. {
  872. SECItem my = *si;
  873. if (SECSuccess != SECU_StripTagAndLength(&my) || !my.len)
  874. return;
  875. secu_PrintRawString(out, &my, m, level);
  876. }
  877. /* print an unencoded boolean */
  878. static void
  879. secu_PrintBoolean(FILE *out, SECItem *i, const char *m, int level)
  880. {
  881. int val = 0;
  882. if ( i->data && i->len ) {
  883. val = i->data[0];
  884. }
  885. if (!m) {
  886. m = "Boolean";
  887. }
  888. SECU_Indent(out, level);
  889. fprintf(out, "%s: %s\n", m, (val ? "True" : "False"));
  890. }
  891. /*
  892. * Format and print "time". If the tag message "m" is not NULL,
  893. * do indent formatting based on "level" and add a newline afterward;
  894. * otherwise just print the formatted time string only.
  895. */
  896. static void
  897. secu_PrintTime(FILE *out, int64 time, char *m, int level)
  898. {
  899. PRExplodedTime printableTime;
  900. char *timeString;
  901. /* Convert to local time */
  902. PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
  903. timeString = PORT_Alloc(256);
  904. if (timeString == NULL)
  905. return;
  906. if (m != NULL) {
  907. SECU_Indent(out, level);
  908. fprintf(out, "%s: ", m);
  909. }
  910. if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
  911. fprintf(out, timeString);
  912. }
  913. if (m != NULL)
  914. fprintf(out, "\n");
  915. PORT_Free(timeString);
  916. }
  917. /*
  918. * Format and print the UTC Time "t". If the tag message "m" is not NULL,
  919. * do indent formatting based on "level" and add a newline afterward;
  920. * otherwise just print the formatted time string only.
  921. */
  922. void
  923. SECU_PrintUTCTime(FILE *out, SECItem *t, char *m, int level)
  924. {
  925. int64 time;
  926. SECStatus rv;
  927. rv = DER_UTCTimeToTime(&time, t);
  928. if (rv != SECSuccess)
  929. return;
  930. secu_PrintTime(out, time, m, level);
  931. }
  932. /*
  933. * Format and print the Generalized Time "t". If the tag message "m"
  934. * is not NULL, * do indent formatting based on "level" and add a newline
  935. * afterward; otherwise just print the formatted time string only.
  936. */
  937. void
  938. SECU_PrintGeneralizedTime(FILE *out, SECItem *t, char *m, int level)
  939. {
  940. int64 time;
  941. SECStatus rv;
  942. rv = DER_GeneralizedTimeToTime(&time, t);
  943. if (rv != SECSuccess)
  944. return;
  945. secu_PrintTime(out, time, m, level);
  946. }
  947. /*
  948. * Format and print the UTC or Generalized Time "t". If the tag message
  949. * "m" is not NULL, do indent formatting based on "level" and add a newline
  950. * afterward; otherwise just print the formatted time string only.
  951. */
  952. void
  953. SECU_PrintTimeChoice(FILE *out, SECItem *t, char *m, int level)
  954. {
  955. switch (t->type) {
  956. case siUTCTime:
  957. SECU_PrintUTCTime(out, t, m, level);
  958. break;
  959. case siGeneralizedTime:
  960. SECU_PrintGeneralizedTime(out, t, m, level);
  961. break;
  962. default:
  963. PORT_Assert(0);
  964. break;
  965. }
  966. }
  967. /* This prints a SET or SEQUENCE */
  968. void
  969. SECU_PrintSet(FILE *out, SECItem *t, char *m, int level)
  970. {
  971. int type = t->data[0] & SEC_ASN1_TAGNUM_MASK;
  972. int constructed = t->data[0] & SEC_ASN1_CONSTRUCTED;
  973. const char * label;
  974. SECItem my = *t;
  975. if (!constructed) {
  976. SECU_PrintAsHex(out, t, m, level);
  977. return;
  978. }
  979. if (SECSuccess != SECU_StripTagAndLength(&my))
  980. return;
  981. SECU_Indent(out, level);
  982. if (m) {
  983. fprintf(out, "%s: ", m);
  984. }
  985. if (type == SEC_ASN1_SET)
  986. label = "Set ";
  987. else if (type == SEC_ASN1_SEQUENCE)
  988. label = "Sequence ";
  989. else
  990. label = "";
  991. fprintf(out,"%s{\n", label); /* } */
  992. while (my.len >= 2) {
  993. SECItem tmp = my;
  994. if (tmp.data[1] & 0x80) {
  995. unsigned int i;
  996. unsigned int lenlen = tmp.data[1] & 0x7f;
  997. if (lenlen > sizeof tmp.len)
  998. break;
  999. tmp.len = 0;
  1000. for (i=0; i < lenlen; i++) {
  1001. tmp.len = (tmp.len << 8) | tmp.data[2+i];
  1002. }
  1003. tmp.len += lenlen + 2;
  1004. } else {
  1005. tmp.len = tmp.data[1] + 2;
  1006. }
  1007. if (tmp.len > my.len) {
  1008. tmp.len = my.len;
  1009. }
  1010. my.data += tmp.len;
  1011. my.len -= tmp.len;
  1012. SECU_PrintAny(out, &tmp, NULL, level + 1);
  1013. }
  1014. SECU_Indent(out, level); fprintf(out, /* { */ "}\n");
  1015. }
  1016. static void
  1017. secu_PrintContextSpecific(FILE *out, SECItem *i, char *m, int level)
  1018. {
  1019. int type = i->data[0] & SEC_ASN1_TAGNUM_MASK;
  1020. int constructed = i->data[0] & SEC_ASN1_CONSTRUCTED;
  1021. SECItem tmp;
  1022. if (constructed) {
  1023. char * m2;
  1024. if (!m)
  1025. m2 = PR_smprintf("[%d]", type);
  1026. else
  1027. m2 = PR_smprintf("%s: [%d]", m, type);
  1028. if (m2) {
  1029. SECU_PrintSet(out, i, m2, level);
  1030. PR_smprintf_free(m2);
  1031. }
  1032. return;
  1033. }
  1034. SECU_Indent(out, level);
  1035. if (m) {
  1036. fprintf(out, "%s: ", m);
  1037. }
  1038. fprintf(out,"[%d]\n", type);
  1039. tmp = *i;
  1040. if (SECSuccess == SECU_StripTagAndLength(&tmp))
  1041. SECU_PrintAsHex(out, &tmp, m, level+1);
  1042. }
  1043. static void
  1044. secu_PrintOctetString(FILE *out, SECItem *i, char *m, int level)
  1045. {
  1046. SECItem tmp = *i;
  1047. if (SECSuccess == SECU_StripTagAndLength(&tmp))
  1048. SECU_PrintAsHex(out, &tmp, m, level);
  1049. }
  1050. static void
  1051. secu_PrintBitString(FILE *out, SECItem *i, char *m, int level)
  1052. {
  1053. int unused_bits;
  1054. SECItem tmp = *i;
  1055. if (SECSuccess != SECU_StripTagAndLength(&tmp) || tmp.len < 2)
  1056. return;
  1057. unused_bits = *tmp.data++;
  1058. tmp.len--;
  1059. SECU_PrintAsHex(out, &tmp, m, level);
  1060. if (unused_bits) {
  1061. SECU_Indent(out, level + 1);
  1062. fprintf(out, "(%d least significant bits unused)\n", unused_bits);
  1063. }
  1064. }
  1065. /* in a decoded bit string, the len member is a bit length. */
  1066. static void
  1067. secu_PrintDecodedBitString(FILE *out, SECItem *i, char *m, int level)
  1068. {
  1069. int unused_bits;
  1070. SECItem tmp = *i;
  1071. unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
  1072. DER_ConvertBitString(&tmp); /* convert length to byte length */
  1073. SECU_PrintAsHex(out, &tmp, m, level);
  1074. if (unused_bits) {
  1075. SECU_Indent(out, level + 1);
  1076. fprintf(out, "(%d least significant bits unused)\n", unused_bits);
  1077. }
  1078. }
  1079. /* Print a DER encoded Boolean */
  1080. void
  1081. SECU_PrintEncodedBoolean(FILE *out, SECItem *i, char *m, int level)
  1082. {
  1083. SECItem my = *i;
  1084. if (SECSuccess == SECU_StripTagAndLength(&my))
  1085. secu_PrintBoolean(out, &my, m, level);
  1086. }
  1087. /* Print a DER encoded integer */
  1088. void
  1089. SECU_PrintEncodedInteger(FILE *out, SECItem *i, char *m, int level)
  1090. {
  1091. SECItem my = *i;
  1092. if (SECSuccess == SECU_StripTagAndLength(&my))
  1093. SECU_PrintInteger(out, &my, m, level);
  1094. }
  1095. /* Print a DER encoded OID */
  1096. void
  1097. SECU_PrintEncodedObjectID(FILE *out, SECItem *i, char *m, int level)
  1098. {
  1099. SECItem my = *i;
  1100. if (SECSuccess == SECU_StripTagAndLength(&my))
  1101. SECU_PrintObjectID(out, &my, m, level);
  1102. }
  1103. static void
  1104. secu_PrintBMPString(FILE *out, SECItem *i, char *m, int level)
  1105. {
  1106. unsigned char * s;
  1107. unsigned char * d;
  1108. int len;
  1109. SECItem tmp = {0, 0, 0};
  1110. SECItem my = *i;
  1111. if (SECSuccess != SECU_StripTagAndLength(&my))
  1112. goto loser;
  1113. if (my.len % 2)
  1114. goto loser;
  1115. len = (int)(my.len / 2);
  1116. tmp.data = (unsigned char *)PORT_Alloc(len);
  1117. if (!tmp.data)
  1118. goto loser;
  1119. tmp.len = len;
  1120. for (s = my.data, d = tmp.data ; len > 0; len--) {
  1121. PRUint32 bmpChar = (s[0] << 8) | s[1]; s += 2;
  1122. if (!isprint(bmpChar))
  1123. goto loser;
  1124. *d++ = (unsigned char)bmpChar;
  1125. }
  1126. secu_PrintRawString(out, &tmp, m, level);
  1127. PORT_Free(tmp.data);
  1128. return;
  1129. loser:
  1130. SECU_PrintAsHex(out, i, m, level);
  1131. if (tmp.data)
  1132. PORT_Free(tmp.data);
  1133. }
  1134. static void
  1135. secu_PrintUniversalString(FILE *out, SECItem *i, char *m, int level)
  1136. {
  1137. unsigned char * s;
  1138. unsigned char * d;
  1139. int len;
  1140. SECItem tmp = {0, 0, 0};
  1141. SECItem my = *i;
  1142. if (SECSuccess != SECU_StripTagAndLength(&my))
  1143. goto loser;
  1144. if (my.len % 4)
  1145. goto loser;
  1146. len = (int)(my.len / 4);
  1147. tmp.data = (unsigned char *)PORT_Alloc(len);
  1148. if (!tmp.data)
  1149. goto loser;
  1150. tmp.len = len;
  1151. for (s = my.data, d = tmp.data ; len > 0; len--) {
  1152. PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
  1153. s += 4;
  1154. if (!isprint(bmpChar))
  1155. goto loser;
  1156. *d++ = (unsigned char)bmpChar;
  1157. }
  1158. secu_PrintRawString(out, &tmp, m, level);
  1159. PORT_Free(tmp.data);
  1160. return;
  1161. loser:
  1162. SECU_PrintAsHex(out, i, m, level);
  1163. if (tmp.data)
  1164. PORT_Free(tmp.data);
  1165. }
  1166. static void
  1167. secu_PrintUniversal(FILE *out, SECItem *i, char *m, int level)
  1168. {
  1169. switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
  1170. case SEC_ASN1_ENUMERATED:
  1171. case SEC_ASN1_INTEGER:
  1172. SECU_PrintEncodedInteger(out, i, m, level);
  1173. break;
  1174. case SEC_ASN1_OBJECT_ID:
  1175. SECU_PrintEncodedObjectID(out, i, m, level);
  1176. break;
  1177. case SEC_ASN1_BOOLEAN:
  1178. SECU_PrintEncodedBoolean(out, i, m, level);
  1179. break;
  1180. case SEC_ASN1_UTF8_STRING:
  1181. case SEC_ASN1_PRINTABLE_STRING:
  1182. case SEC_ASN1_VISIBLE_STRING:
  1183. case SEC_ASN1_IA5_STRING:
  1184. case SEC_ASN1_T61_STRING:
  1185. SECU_PrintString(out, i, m, level);
  1186. break;
  1187. case SEC_ASN1_GENERALIZED_TIME:
  1188. SECU_PrintGeneralizedTime(out, i, m, level);
  1189. break;
  1190. case SEC_ASN1_UTC_TIME:
  1191. SECU_PrintUTCTime(out, i, m, level);
  1192. break;
  1193. case SEC_ASN1_NULL:
  1194. SECU_Indent(out, level);
  1195. if (m && m[0])
  1196. fprintf(out, "%s: NULL\n", m);
  1197. else
  1198. fprintf(out, "NULL\n");
  1199. break;
  1200. case SEC_ASN1_SET:
  1201. case SEC_ASN1_SEQUENCE:
  1202. SECU_PrintSet(out, i, m, level);
  1203. break;
  1204. case SEC_ASN1_OCTET_STRING:
  1205. secu_PrintOctetString(out, i, m, level);
  1206. break;
  1207. case SEC_ASN1_BIT_STRING:
  1208. secu_PrintBitString(out, i, m, level);
  1209. break;
  1210. case SEC_ASN1_BMP_STRING:
  1211. secu_PrintBMPString(out, i, m, level);
  1212. break;
  1213. case SEC_ASN1_UNIVERSAL_STRING:
  1214. secu_PrintUniversalString(out, i, m, level);
  1215. break;
  1216. default:
  1217. SECU_PrintAsHex(out, i, m, level);
  1218. break;
  1219. }
  1220. }
  1221. void
  1222. SECU_PrintAny(FILE *out, SECItem *i, char *m, int level)
  1223. {
  1224. if ( i && i->len && i->data ) {
  1225. switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
  1226. case SEC_ASN1_CONTEXT_SPECIFIC:
  1227. secu_PrintContextSpecific(out, i, m, level);
  1228. break;
  1229. case SEC_ASN1_UNIVERSAL:
  1230. secu_PrintUniversal(out, i, m, level);
  1231. break;
  1232. default:
  1233. SECU_PrintAsHex(out, i, m, level);
  1234. break;
  1235. }
  1236. }
  1237. }
  1238. static int
  1239. secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
  1240. {
  1241. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  1242. SECU_PrintTimeChoice(out, &v->notBefore, "Not Before", level+1);
  1243. SECU_PrintTimeChoice(out, &v->notAfter, "Not After ", level+1);
  1244. return 0;
  1245. }
  1246. /* This function does NOT expect a DER type and length. */
  1247. SECOidTag
  1248. SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level)
  1249. {
  1250. SECOidData *oiddata;
  1251. char * oidString = NULL;
  1252. oiddata = SECOID_FindOID(oid);
  1253. if (oiddata != NULL) {
  1254. const char *name = oiddata->desc;
  1255. SECU_Indent(out, level);
  1256. if (m != NULL)
  1257. fprintf(out, "%s: ", m);
  1258. fprintf(out, "%s\n", name);
  1259. return oiddata->offset;
  1260. }
  1261. oidString = CERT_GetOidString(oid);
  1262. if (oidString) {
  1263. SECU_Indent(out, level);
  1264. if (m != NULL)
  1265. fprintf(out, "%s: ", m);
  1266. fprintf(out, "%s\n", oidString);
  1267. PR_smprintf_free(oidString);
  1268. return SEC_OID_UNKNOWN;
  1269. }
  1270. SECU_PrintAsHex(out, oid, m, level);
  1271. return SEC_OID_UNKNOWN;
  1272. }
  1273. typedef struct secuPBEParamsStr {
  1274. SECItem salt;
  1275. SECItem iterationCount;
  1276. SECItem keyLength;
  1277. SECAlgorithmID cipherAlg;
  1278. SECAlgorithmID kdfAlg;
  1279. } secuPBEParams;
  1280. SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate);
  1281. /* SECOID_PKCS5_PBKDF2 */
  1282. const SEC_ASN1Template secuKDF2Params[] =
  1283. {
  1284. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
  1285. { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
  1286. { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
  1287. { SEC_ASN1_INTEGER, offsetof(secuPBEParams, keyLength) },
  1288. { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
  1289. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1290. { 0 }
  1291. };
  1292. /* PKCS5v1 & PKCS12 */
  1293. const SEC_ASN1Template secuPBEParamsTemp[] =
  1294. {
  1295. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
  1296. { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
  1297. { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
  1298. { 0 }
  1299. };
  1300. /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
  1301. const SEC_ASN1Template secuPBEV2Params[] =
  1302. {
  1303. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams)},
  1304. { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
  1305. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1306. { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, cipherAlg),
  1307. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1308. { 0 }
  1309. };
  1310. void
  1311. secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level)
  1312. {
  1313. PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1314. SECStatus rv;
  1315. secuPBEParams param;
  1316. if (m) {
  1317. SECU_Indent(out, level);
  1318. fprintf (out, "%s:\n", m);
  1319. }
  1320. if (!pool) {
  1321. SECU_Indent(out, level);
  1322. fprintf(out, "Out of memory\n");
  1323. return;
  1324. }
  1325. PORT_Memset(&param, 0, sizeof param);
  1326. rv = SEC_QuickDERDecodeItem(pool, &param, secuKDF2Params, value);
  1327. if (rv == SECSuccess) {
  1328. SECU_PrintAsHex(out, &param.salt, "Salt", level+1);
  1329. SECU_PrintInteger(out, &param.iterationCount, "Iteration Count",
  1330. level+1);
  1331. SECU_PrintInteger(out, &param.keyLength, "Key Length", level+1);
  1332. SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF algorithm", level+1);
  1333. }
  1334. PORT_FreeArena(pool, PR_FALSE);
  1335. }
  1336. void
  1337. secu_PrintPKCS5V2Params(FILE *out, SECItem *value, char *m, int level)
  1338. {
  1339. PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1340. SECStatus rv;
  1341. secuPBEParams param;
  1342. if (m) {
  1343. SECU_Indent(out, level);
  1344. fprintf (out, "%s:\n", m);
  1345. }
  1346. if (!pool) {
  1347. SECU_Indent(out, level);
  1348. fprintf(out, "Out of memory\n");
  1349. return;
  1350. }
  1351. PORT_Memset(&param, 0, sizeof param);
  1352. rv = SEC_QuickDERDecodeItem(pool, &param, secuPBEV2Params, value);
  1353. if (rv == SECSuccess) {
  1354. SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF", level+1);
  1355. SECU_PrintAlgorithmID(out, &param.cipherAlg, "Cipher", level+1);
  1356. }
  1357. PORT_FreeArena(pool, PR_FALSE);
  1358. }
  1359. void
  1360. secu_PrintPBEParams(FILE *out, SECItem *value, char *m, int level)
  1361. {
  1362. PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1363. SECStatus rv;
  1364. secuPBEParams param;
  1365. if (m) {
  1366. SECU_Indent(out, level);
  1367. fprintf (out, "%s:\n", m);
  1368. }
  1369. if (!pool) {
  1370. SECU_Indent(out, level);
  1371. fprintf(out, "Out of memory\n");
  1372. return;
  1373. }
  1374. PORT_Memset(&param, 0, sizeof(secuPBEParams));
  1375. rv = SEC_QuickDERDecodeItem(pool, &param, secuPBEParamsTemp, value);
  1376. if (rv == SECSuccess) {
  1377. SECU_PrintAsHex(out, &param.salt, "Salt", level+1);
  1378. SECU_PrintInteger(out, &param.iterationCount, "Iteration Count",
  1379. level+1);
  1380. }
  1381. PORT_FreeArena(pool, PR_FALSE);
  1382. }
  1383. /* This function does NOT expect a DER type and length. */
  1384. void
  1385. SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
  1386. {
  1387. SECOidTag algtag;
  1388. SECU_PrintObjectID(out, &a->algorithm, m, level);
  1389. algtag = SECOID_GetAlgorithmTag(a);
  1390. if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag)) {
  1391. switch (algtag) {
  1392. case SEC_OID_PKCS5_PBKDF2:
  1393. secu_PrintKDF2Params(out, &a->parameters, "Parameters", level+1);
  1394. break;
  1395. case SEC_OID_PKCS5_PBES2:
  1396. secu_PrintPKCS5V2Params(out, &a->parameters, "Encryption", level+1);
  1397. break;
  1398. case SEC_OID_PKCS5_PBMAC1:
  1399. secu_PrintPKCS5V2Params(out, &a->parameters, "MAC", level+1);
  1400. break;
  1401. default:
  1402. secu_PrintPBEParams(out, &a->parameters, "Parameters", level+1);
  1403. break;
  1404. }
  1405. return;
  1406. }
  1407. if (a->parameters.len == 0
  1408. || (a->parameters.len == 2
  1409. && PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
  1410. /* No arguments or NULL argument */
  1411. } else {
  1412. /* Print args to algorithm */
  1413. SECU_PrintAsHex(out, &a->parameters, "Args", level+1);
  1414. }
  1415. }
  1416. static void
  1417. secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
  1418. {
  1419. SECItem *value;
  1420. int i;
  1421. char om[100];
  1422. if (m) {
  1423. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  1424. }
  1425. /*
  1426. * Should make this smarter; look at the type field and then decode
  1427. * and print the value(s) appropriately!
  1428. */
  1429. SECU_PrintObjectID(out, &(attr->type), "Type", level+1);
  1430. if (attr->values != NULL) {
  1431. i = 0;
  1432. while ((value = attr->values[i++]) != NULL) {
  1433. sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
  1434. if (attr->encoded || attr->typeTag == NULL) {
  1435. SECU_PrintAny(out, value, om, level+1);
  1436. } else {
  1437. switch (attr->typeTag->offset) {
  1438. default:
  1439. SECU_PrintAsHex(out, value, om, level+1);
  1440. break;
  1441. case SEC_OID_PKCS9_CONTENT_TYPE:
  1442. SECU_PrintObjectID(out, value, om, level+1);
  1443. break;
  1444. case SEC_OID_PKCS9_SIGNING_TIME:
  1445. SECU_PrintTimeChoice(out, value, om, level+1);
  1446. break;
  1447. }
  1448. }
  1449. }
  1450. }
  1451. }
  1452. static void
  1453. secu_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
  1454. {
  1455. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  1456. SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level+1);
  1457. SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level+1);
  1458. if (pk->u.rsa.publicExponent.len == 1 &&
  1459. pk->u.rsa.publicExponent.data[0] == 1) {
  1460. SECU_Indent(out, level +1); fprintf(out, "Error: INVALID RSA KEY!\n");
  1461. }
  1462. }
  1463. static void
  1464. secu_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
  1465. {
  1466. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  1467. SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level+1);
  1468. SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level+1);
  1469. SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level+1);
  1470. SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level+1);
  1471. }
  1472. #ifdef NSS_ENABLE_ECC
  1473. static void
  1474. secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
  1475. {
  1476. SECItem curveOID = { siBuffer, NULL, 0};
  1477. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  1478. SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level+1);
  1479. /* For named curves, the DEREncodedParams field contains an
  1480. * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
  1481. */
  1482. if ((pk->u.ec.DEREncodedParams.len > 2) &&
  1483. (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
  1484. curveOID.len = pk->u.ec.DEREncodedParams.data[1];
  1485. curveOID.data = pk->u.ec.DEREncodedParams.data + 2;
  1486. SECU_PrintObjectID(out, &curveOID, "Curve", level +1);
  1487. }
  1488. }
  1489. #endif /* NSS_ENABLE_ECC */
  1490. static void
  1491. secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena,
  1492. CERTSubjectPublicKeyInfo *i, char *msg, int level)
  1493. {
  1494. SECKEYPublicKey *pk;
  1495. SECU_Indent(out, level); fprintf(out, "%s:\n", msg);
  1496. SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level+1);
  1497. pk = SECKEY_ExtractPublicKey(i);
  1498. if (pk) {
  1499. switch (pk->keyType) {
  1500. case rsaKey:
  1501. secu_PrintRSAPublicKey(out, pk, "RSA Public Key", level +1);
  1502. break;
  1503. case dsaKey:
  1504. secu_PrintDSAPublicKey(out, pk, "DSA Public Key", level +1);
  1505. break;
  1506. #ifdef NSS_ENABLE_ECC
  1507. case ecKey:
  1508. secu_PrintECPublicKey(out, pk, "EC Public Key", level +1);
  1509. break;
  1510. #endif
  1511. case dhKey:
  1512. case fortezzaKey:
  1513. case keaKey:
  1514. SECU_Indent(out, level);
  1515. fprintf(out, "unable to format this SPKI algorithm type\n");
  1516. goto loser;
  1517. default:
  1518. SECU_Indent(out, level);
  1519. fprintf(out, "unknown SPKI algorithm type\n");
  1520. goto loser;
  1521. }
  1522. PORT_FreeArena(pk->arena, PR_FALSE);
  1523. } else {
  1524. SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
  1525. loser:
  1526. if (i->subjectPublicKey.data) {
  1527. SECU_PrintAny(out, &i->subjectPublicKey, "Raw", level);
  1528. }
  1529. }
  1530. }
  1531. static SECStatus
  1532. secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
  1533. {
  1534. SECItem decodedValue;
  1535. SECStatus rv;
  1536. int64 invalidTime;
  1537. char *formattedTime = NULL;
  1538. decodedValue.data = NULL;
  1539. rv = SEC_ASN1DecodeItem (NULL, &decodedValue,
  1540. SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
  1541. value);
  1542. if (rv == SECSuccess) {
  1543. rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
  1544. if (rv == SECSuccess) {
  1545. formattedTime = CERT_GenTime2FormattedAscii
  1546. (invalidTime, "%a %b %d %H:%M:%S %Y");
  1547. SECU_Indent(out, level +1);
  1548. fprintf (out, "%s: %s\n", msg, formattedTime);
  1549. PORT_Free (formattedTime);
  1550. }
  1551. }
  1552. PORT_Free (decodedValue.data);
  1553. return (rv);
  1554. }
  1555. static SECStatus
  1556. PrintExtKeyUsageExtension (FILE *out, SECItem *value, char *msg, int level)
  1557. {
  1558. CERTOidSequence *os;
  1559. SECItem **op;
  1560. os = CERT_DecodeOidSequence(value);
  1561. if( (CERTOidSequence *)NULL == os ) {
  1562. return SECFailure;
  1563. }
  1564. for( op = os->oids; *op; op++ ) {
  1565. SECU_PrintObjectID(out, *op, msg, level + 1);
  1566. }
  1567. CERT_DestroyOidSequence(os);
  1568. return SECSuccess;
  1569. }
  1570. static SECStatus
  1571. secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level) {
  1572. CERTBasicConstraints constraints;
  1573. SECStatus rv;
  1574. SECU_Indent(out, level);
  1575. if (msg) {
  1576. fprintf(out,"%s: ",msg);
  1577. }
  1578. rv = CERT_DecodeBasicConstraintValue(&constraints,value);
  1579. if (rv == SECSuccess && constraints.isCA) {
  1580. if (constraints.pathLenConstraint >= 0) {
  1581. fprintf(out,"Is a CA with a maximum path length of %d.\n",
  1582. constraints.pathLenConstraint);
  1583. } else {
  1584. fprintf(out,"Is a CA with no maximum path length.\n");
  1585. }
  1586. } else {
  1587. fprintf(out,"Is not a CA.\n");
  1588. }
  1589. return SECSuccess;
  1590. }
  1591. static const char * const nsTypeBits[] = {
  1592. "SSL Client",
  1593. "SSL Server",
  1594. "S/MIME",
  1595. "Object Signing",
  1596. "Reserved",
  1597. "SSL CA",
  1598. "S/MIME CA",
  1599. "ObjectSigning CA"
  1600. };
  1601. /* NSCertType is merely a bit string whose bits are displayed symbolically */
  1602. static SECStatus
  1603. secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
  1604. {
  1605. int unused;
  1606. int NS_Type;
  1607. int i;
  1608. int found = 0;
  1609. SECItem my = *value;
  1610. if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
  1611. SECSuccess != SECU_StripTagAndLength(&my)) {
  1612. SECU_PrintAny(out, value, "Data", level);
  1613. return SECSuccess;
  1614. }
  1615. unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
  1616. NS_Type = my.data[1] & (0xff << unused);
  1617. SECU_Indent(out, level);
  1618. if (msg) {
  1619. fprintf(out,"%s: ",msg);
  1620. } else {
  1621. fprintf(out,"Netscape Certificate Type: ");
  1622. }
  1623. for (i=0; i < 8; i++) {
  1624. if ( (0x80 >> i) & NS_Type) {
  1625. fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
  1626. found = 1;
  1627. }
  1628. }
  1629. fprintf(out, (found ? ">\n" : "none\n"));
  1630. return SECSuccess;
  1631. }
  1632. static const char * const usageBits[] = {
  1633. "Digital Signature", /* 0x80 */
  1634. "Non-Repudiation", /* 0x40 */
  1635. "Key Encipherment", /* 0x20 */
  1636. "Data Encipherment", /* 0x10 */
  1637. "Key Agreement", /* 0x08 */
  1638. "Certificate Signing", /* 0x04 */
  1639. "CRL Signing", /* 0x02 */
  1640. "Encipher Only", /* 0x01 */
  1641. "Decipher Only", /* 0x0080 */
  1642. NULL
  1643. };
  1644. /* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
  1645. static void
  1646. secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
  1647. {
  1648. int unused;
  1649. int usage;
  1650. int i;
  1651. int found = 0;
  1652. SECItem my = *value;
  1653. if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
  1654. SECSuccess != SECU_StripTagAndLength(&my)) {
  1655. SECU_PrintAny(out, value, "Data", level);
  1656. return;
  1657. }
  1658. unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
  1659. usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
  1660. : (my.data[1] << 8) |
  1661. (my.data[2] & (0xff << unused));
  1662. SECU_Indent(out, level);
  1663. fprintf(out, "Usages: ");
  1664. for (i=0; usageBits[i]; i++) {
  1665. if ( (0x8000 >> i) & usage) {
  1666. if (found)
  1667. SECU_Indent(out, level + 2);
  1668. fprintf(out, "%s\n", usageBits[i]);
  1669. found = 1;
  1670. }
  1671. }
  1672. if (!found) {
  1673. fprintf(out, "(none)\n");
  1674. }
  1675. }
  1676. static void
  1677. secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
  1678. {
  1679. PRStatus st;
  1680. PRNetAddr addr;
  1681. char addrBuf[80];
  1682. memset(&addr, 0, sizeof addr);
  1683. if (value->len == 4) {
  1684. addr.inet.family = PR_AF_INET;
  1685. memcpy(&addr.inet.ip, value->data, value->len);
  1686. } else if (value->len == 16) {
  1687. addr.ipv6.family = PR_AF_INET6;
  1688. memcpy(addr.ipv6.ip.pr_s6_addr, value->data, value->len);
  1689. if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
  1690. /* convert to IPv4. */
  1691. addr.inet.family = PR_AF_INET;
  1692. memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
  1693. memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
  1694. }
  1695. } else {
  1696. goto loser;
  1697. }
  1698. st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
  1699. if (st == PR_SUCCESS) {
  1700. SECU_Indent(out, level);
  1701. fprintf(out, "%s: %s\n", msg, addrBuf);
  1702. } else {
  1703. loser:
  1704. SECU_PrintAsHex(out, value, msg, level);
  1705. }
  1706. }
  1707. static void
  1708. secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
  1709. {
  1710. char label[40];
  1711. if (msg && msg[0]) {
  1712. SECU_Indent(out, level++); fprintf(out, "%s: \n", msg);
  1713. }
  1714. switch (gname->type) {
  1715. case certOtherName :
  1716. SECU_PrintAny( out, &gname->name.OthName.name, "Other Name", level);
  1717. SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level+1);
  1718. break;
  1719. case certDirectoryName :
  1720. SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
  1721. break;
  1722. case certRFC822Name :
  1723. secu_PrintRawString( out, &gname->name.other, "RFC822 Name", level);
  1724. break;
  1725. case certDNSName :
  1726. secu_PrintRawString( out, &gname->name.other, "DNS name", level);
  1727. break;
  1728. case certURI :
  1729. secu_PrintRawString( out, &gname->name.other, "URI", level);
  1730. break;
  1731. case certIPAddress :
  1732. secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
  1733. break;
  1734. case certRegisterID :
  1735. SECU_PrintObjectID( out, &gname->name.other, "Registered ID", level);
  1736. break;
  1737. case certX400Address :
  1738. SECU_PrintAny( out, &gname->name.other, "X400 Address", level);
  1739. break;
  1740. case certEDIPartyName :
  1741. SECU_PrintAny( out, &gname->name.other, "EDI Party", level);
  1742. break;
  1743. default:
  1744. PR_snprintf(label, sizeof label, "unknown type [%d]",
  1745. (int)gname->type - 1);
  1746. SECU_PrintAsHex(out, &gname->name.other, label, level);
  1747. break;
  1748. }
  1749. }
  1750. static void
  1751. secu_PrintGeneralNames(FILE *out, CERTGeneralName *gname, char *msg, int level)
  1752. {
  1753. CERTGeneralName *name = gname;
  1754. do {
  1755. secu_PrintGeneralName(out, name, msg, level);
  1756. name = CERT_GetNextGeneralName(name);
  1757. } while (name && name != gnam

Large files files are truncated, but you can click here to view the full file