PageRenderTime 67ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/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
  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 != gname);
  1758. }
  1759. static void
  1760. secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
  1761. {
  1762. CERTAuthKeyID *kid = NULL;
  1763. PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1764. if (!pool) {
  1765. SECU_PrintError("Error", "Allocating new ArenaPool");
  1766. return;
  1767. }
  1768. kid = CERT_DecodeAuthKeyID(pool, value);
  1769. if (!kid) {
  1770. SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
  1771. SECU_PrintAny(out, value, "Data", level);
  1772. } else {
  1773. int keyIDPresent = (kid->keyID.data && kid->keyID.len);
  1774. int issuerPresent = kid->authCertIssuer != NULL;
  1775. int snPresent = (kid->authCertSerialNumber.data &&
  1776. kid->authCertSerialNumber.len);
  1777. if (keyIDPresent)
  1778. SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
  1779. if (issuerPresent)
  1780. secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
  1781. if (snPresent)
  1782. SECU_PrintInteger(out, &kid->authCertSerialNumber,
  1783. "Serial Number", level);
  1784. }
  1785. PORT_FreeArena(pool, PR_FALSE);
  1786. }
  1787. static void
  1788. secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
  1789. {
  1790. CERTGeneralName * nameList;
  1791. CERTGeneralName * current;
  1792. PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1793. if (!pool) {
  1794. SECU_PrintError("Error", "Allocating new ArenaPool");
  1795. return;
  1796. }
  1797. nameList = current = CERT_DecodeAltNameExtension(pool, value);
  1798. if (!current) {
  1799. if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
  1800. /* Decoder found empty sequence, which is invalid. */
  1801. PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
  1802. }
  1803. SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
  1804. SECU_PrintAny(out, value, "Data", level);
  1805. } else {
  1806. do {
  1807. secu_PrintGeneralName(out, current, msg, level);
  1808. current = CERT_GetNextGeneralName(current);
  1809. } while (current != nameList);
  1810. }
  1811. PORT_FreeArena(pool, PR_FALSE);
  1812. }
  1813. static void
  1814. secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
  1815. {
  1816. CERTCrlDistributionPoints * dPoints;
  1817. PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1818. if (!pool) {
  1819. SECU_PrintError("Error", "Allocating new ArenaPool");
  1820. return;
  1821. }
  1822. dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
  1823. if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
  1824. CRLDistributionPoint ** pPoints = dPoints->distPoints;
  1825. CRLDistributionPoint * pPoint;
  1826. while (NULL != (pPoint = *pPoints++)) {
  1827. if (pPoint->distPointType == generalName &&
  1828. pPoint->distPoint.fullName != NULL) {
  1829. secu_PrintGeneralNames(out, pPoint->distPoint.fullName, NULL,
  1830. level);
  1831. } else if (pPoint->distPointType == relativeDistinguishedName &&
  1832. pPoint->distPoint.relativeName.avas) {
  1833. SECU_PrintRDN(out, &pPoint->distPoint.relativeName, "RDN",
  1834. level);
  1835. } else if (pPoint->derDistPoint.data) {
  1836. SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level);
  1837. }
  1838. if (pPoint->reasons.data) {
  1839. secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
  1840. level);
  1841. }
  1842. if (pPoint->crlIssuer) {
  1843. secu_PrintGeneralName(out, pPoint->crlIssuer, "Issuer", level);
  1844. }
  1845. }
  1846. } else {
  1847. SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
  1848. SECU_PrintAny(out, value, "Data", level);
  1849. }
  1850. PORT_FreeArena(pool, PR_FALSE);
  1851. }
  1852. static void
  1853. secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
  1854. char *msg, int level)
  1855. {
  1856. CERTNameConstraint *head = value;
  1857. SECU_Indent(out, level); fprintf(out, "%s Subtree:\n", msg);
  1858. level++;
  1859. do {
  1860. secu_PrintGeneralName(out, &value->name, NULL, level);
  1861. if (value->min.data)
  1862. SECU_PrintInteger(out, &value->min, "Minimum", level+1);
  1863. if (value->max.data)
  1864. SECU_PrintInteger(out, &value->max, "Maximum", level+1);
  1865. value = CERT_GetNextNameConstraint(value);
  1866. } while (value != head);
  1867. }
  1868. static void
  1869. secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
  1870. {
  1871. CERTNameConstraints * cnstrnts;
  1872. PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1873. if (!pool) {
  1874. SECU_PrintError("Error", "Allocating new ArenaPool");
  1875. return;
  1876. }
  1877. cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
  1878. if (!cnstrnts) {
  1879. SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
  1880. SECU_PrintAny(out, value, "Raw", level);
  1881. } else {
  1882. if (cnstrnts->permited)
  1883. secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
  1884. "Permitted", level);
  1885. if (cnstrnts->excluded)
  1886. secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
  1887. "Excluded", level);
  1888. }
  1889. PORT_FreeArena(pool, PR_FALSE);
  1890. }
  1891. static void
  1892. secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
  1893. {
  1894. CERTAuthInfoAccess **infos = NULL;
  1895. PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1896. if (!pool) {
  1897. SECU_PrintError("Error", "Allocating new ArenaPool");
  1898. return;
  1899. }
  1900. infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
  1901. if (!infos) {
  1902. SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
  1903. SECU_PrintAny(out, value, "Raw", level);
  1904. } else {
  1905. CERTAuthInfoAccess *info;
  1906. while (NULL != (info = *infos++)) {
  1907. if (info->method.data) {
  1908. SECU_PrintObjectID(out, &info->method, "Method", level);
  1909. } else {
  1910. SECU_Indent(out,level);
  1911. fprintf(out, "Error: missing method\n");
  1912. }
  1913. if (info->location) {
  1914. secu_PrintGeneralName(out, info->location, "Location", level);
  1915. } else {
  1916. SECU_PrintAny(out, &info->derLocation, "Location", level);
  1917. }
  1918. }
  1919. }
  1920. PORT_FreeArena(pool, PR_FALSE);
  1921. }
  1922. void
  1923. SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
  1924. char *msg, int level)
  1925. {
  1926. SECOidTag oidTag;
  1927. if ( extensions ) {
  1928. if (msg && *msg) {
  1929. SECU_Indent(out, level++); fprintf(out, "%s:\n", msg);
  1930. }
  1931. while ( *extensions ) {
  1932. SECItem *tmpitem;
  1933. tmpitem = &(*extensions)->id;
  1934. SECU_PrintObjectID(out, tmpitem, "Name", level);
  1935. tmpitem = &(*extensions)->critical;
  1936. if ( tmpitem->len ) {
  1937. secu_PrintBoolean(out, tmpitem, "Critical", level);
  1938. }
  1939. oidTag = SECOID_FindOIDTag (&((*extensions)->id));
  1940. tmpitem = &((*extensions)->value);
  1941. switch (oidTag) {
  1942. case SEC_OID_X509_INVALID_DATE:
  1943. case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
  1944. secu_PrintX509InvalidDate(out, tmpitem, "Date", level );
  1945. break;
  1946. case SEC_OID_X509_CERTIFICATE_POLICIES:
  1947. SECU_PrintPolicy(out, tmpitem, "Data", level );
  1948. break;
  1949. case SEC_OID_NS_CERT_EXT_BASE_URL:
  1950. case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
  1951. case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
  1952. case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
  1953. case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
  1954. case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
  1955. case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
  1956. case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
  1957. case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
  1958. case SEC_OID_OCSP_RESPONDER:
  1959. SECU_PrintString(out,tmpitem, "URL", level);
  1960. break;
  1961. case SEC_OID_NS_CERT_EXT_COMMENT:
  1962. SECU_PrintString(out,tmpitem, "Comment", level);
  1963. break;
  1964. case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
  1965. SECU_PrintString(out,tmpitem, "ServerName", level);
  1966. break;
  1967. case SEC_OID_NS_CERT_EXT_CERT_TYPE:
  1968. secu_PrintNSCertType(out,tmpitem,"Data",level);
  1969. break;
  1970. case SEC_OID_X509_BASIC_CONSTRAINTS:
  1971. secu_PrintBasicConstraints(out,tmpitem,"Data",level);
  1972. break;
  1973. case SEC_OID_X509_EXT_KEY_USAGE:
  1974. PrintExtKeyUsageExtension(out, tmpitem, NULL, level);
  1975. break;
  1976. case SEC_OID_X509_KEY_USAGE:
  1977. secu_PrintX509KeyUsage(out, tmpitem, NULL, level );
  1978. break;
  1979. case SEC_OID_X509_AUTH_KEY_ID:
  1980. secu_PrintAuthKeyIDExtension(out, tmpitem, NULL, level );
  1981. break;
  1982. case SEC_OID_X509_SUBJECT_ALT_NAME:
  1983. case SEC_OID_X509_ISSUER_ALT_NAME:
  1984. secu_PrintAltNameExtension(out, tmpitem, NULL, level );
  1985. break;
  1986. case SEC_OID_X509_CRL_DIST_POINTS:
  1987. secu_PrintCRLDistPtsExtension(out, tmpitem, NULL, level );
  1988. break;
  1989. case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
  1990. SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL,
  1991. level );
  1992. break;
  1993. case SEC_OID_X509_NAME_CONSTRAINTS:
  1994. secu_PrintNameConstraintsExtension(out, tmpitem, NULL, level);
  1995. break;
  1996. case SEC_OID_X509_AUTH_INFO_ACCESS:
  1997. secu_PrintAuthorityInfoAcess(out, tmpitem, NULL, level);
  1998. break;
  1999. case SEC_OID_X509_CRL_NUMBER:
  2000. case SEC_OID_X509_REASON_CODE:
  2001. /* PKIX OIDs */
  2002. case SEC_OID_PKIX_OCSP:
  2003. case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
  2004. case SEC_OID_PKIX_OCSP_NONCE:
  2005. case SEC_OID_PKIX_OCSP_CRL:
  2006. case SEC_OID_PKIX_OCSP_RESPONSE:
  2007. case SEC_OID_PKIX_OCSP_NO_CHECK:
  2008. case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
  2009. case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
  2010. case SEC_OID_PKIX_REGCTRL_REGTOKEN:
  2011. case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
  2012. case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
  2013. case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
  2014. case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
  2015. case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
  2016. case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
  2017. case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
  2018. /* Netscape extension OIDs. */
  2019. case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
  2020. case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
  2021. case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
  2022. case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
  2023. case SEC_OID_NS_CERT_EXT_USER_PICTURE:
  2024. /* x.509 v3 Extensions */
  2025. case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
  2026. case SEC_OID_X509_SUBJECT_KEY_ID:
  2027. case SEC_OID_X509_POLICY_MAPPINGS:
  2028. case SEC_OID_X509_POLICY_CONSTRAINTS:
  2029. default:
  2030. SECU_PrintAny(out, tmpitem, "Data", level);
  2031. break;
  2032. }
  2033. secu_Newline(out);
  2034. extensions++;
  2035. }
  2036. }
  2037. }
  2038. /* An RDN is a subset of a DirectoryName, and we already know how to
  2039. * print those, so make a directory name out of the RDN, and print it.
  2040. */
  2041. void
  2042. SECU_PrintRDN(FILE *out, CERTRDN *rdn, char *msg, int level)
  2043. {
  2044. CERTName name;
  2045. CERTRDN *rdns[2];
  2046. name.arena = NULL;
  2047. name.rdns = rdns;
  2048. rdns[0] = rdn;
  2049. rdns[1] = NULL;
  2050. SECU_PrintName(out, &name, msg, level);
  2051. }
  2052. void
  2053. SECU_PrintName(FILE *out, CERTName *name, char *msg, int level)
  2054. {
  2055. char *nameStr;
  2056. char *str;
  2057. SECItem my;
  2058. if (!name) {
  2059. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  2060. return;
  2061. }
  2062. if (!name->rdns || !name->rdns[0]) {
  2063. str = "(empty)";
  2064. } else {
  2065. str = nameStr = CERT_NameToAscii(name);
  2066. }
  2067. if (!str) {
  2068. str = "!Invalid AVA!";
  2069. }
  2070. my.data = (unsigned char *)str;
  2071. my.len = PORT_Strlen(str);
  2072. #if 1
  2073. secu_PrintRawString(out, &my, msg, level);
  2074. #else
  2075. SECU_Indent(out, level); fprintf(out, "%s: ", msg);
  2076. fprintf(out, str);
  2077. secu_Newline(out);
  2078. #endif
  2079. PORT_Free(nameStr);
  2080. }
  2081. void
  2082. printflags(char *trusts, unsigned int flags)
  2083. {
  2084. if (flags & CERTDB_VALID_CA)
  2085. if (!(flags & CERTDB_TRUSTED_CA) &&
  2086. !(flags & CERTDB_TRUSTED_CLIENT_CA))
  2087. PORT_Strcat(trusts, "c");
  2088. if (flags & CERTDB_VALID_PEER)
  2089. if (!(flags & CERTDB_TRUSTED))
  2090. PORT_Strcat(trusts, "p");
  2091. if (flags & CERTDB_TRUSTED_CA)
  2092. PORT_Strcat(trusts, "C");
  2093. if (flags & CERTDB_TRUSTED_CLIENT_CA)
  2094. PORT_Strcat(trusts, "T");
  2095. if (flags & CERTDB_TRUSTED)
  2096. PORT_Strcat(trusts, "P");
  2097. if (flags & CERTDB_USER)
  2098. PORT_Strcat(trusts, "u");
  2099. if (flags & CERTDB_SEND_WARN)
  2100. PORT_Strcat(trusts, "w");
  2101. if (flags & CERTDB_INVISIBLE_CA)
  2102. PORT_Strcat(trusts, "I");
  2103. if (flags & CERTDB_GOVT_APPROVED_CA)
  2104. PORT_Strcat(trusts, "G");
  2105. return;
  2106. }
  2107. /* callback for listing certs through pkcs11 */
  2108. SECStatus
  2109. SECU_PrintCertNickname(CERTCertListNode *node, void *data)
  2110. {
  2111. CERTCertTrust *trust;
  2112. CERTCertificate* cert;
  2113. FILE *out;
  2114. char trusts[30];
  2115. char *name;
  2116. cert = node->cert;
  2117. PORT_Memset (trusts, 0, sizeof (trusts));
  2118. out = (FILE *)data;
  2119. name = node->appData;
  2120. if (!name || !name[0]) {
  2121. name = cert->nickname;
  2122. }
  2123. if (!name || !name[0]) {
  2124. name = cert->emailAddr;
  2125. }
  2126. if (!name || !name[0]) {
  2127. name = "(NULL)";
  2128. }
  2129. trust = cert->trust;
  2130. if (trust) {
  2131. printflags(trusts, trust->sslFlags);
  2132. PORT_Strcat(trusts, ",");
  2133. printflags(trusts, trust->emailFlags);
  2134. PORT_Strcat(trusts, ",");
  2135. printflags(trusts, trust->objectSigningFlags);
  2136. } else {
  2137. PORT_Memcpy(trusts,",,",3);
  2138. }
  2139. fprintf(out, "%-60s %-5s\n", name, trusts);
  2140. return (SECSuccess);
  2141. }
  2142. int
  2143. SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
  2144. {
  2145. CERTCertExtension **extensions = NULL;
  2146. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2147. int rv = 0;
  2148. if (!arena)
  2149. return SEC_ERROR_NO_MEMORY;
  2150. rv = SEC_QuickDERDecodeItem(arena, &extensions,
  2151. SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate), any);
  2152. if (!rv)
  2153. SECU_PrintExtensions(out, extensions, m, level);
  2154. else
  2155. SECU_PrintAny(out, any, m, level);
  2156. PORT_FreeArena(arena, PR_FALSE);
  2157. return rv;
  2158. }
  2159. /* print a decoded SET OF or SEQUENCE OF Extensions */
  2160. int
  2161. SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
  2162. {
  2163. int rv = 0;
  2164. if (m && *m) {
  2165. SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
  2166. }
  2167. while (any && any[0]) {
  2168. rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
  2169. any++;
  2170. }
  2171. return rv;
  2172. }
  2173. /* print a decoded SET OF or SEQUENCE OF "ANY" */
  2174. int
  2175. SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
  2176. {
  2177. int rv = 0;
  2178. if (m && *m) {
  2179. SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
  2180. }
  2181. while (any && any[0]) {
  2182. SECU_PrintAny(out, any[0], "", level);
  2183. any++;
  2184. }
  2185. return rv;
  2186. }
  2187. int
  2188. SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
  2189. {
  2190. int rv = 0;
  2191. SECOidTag tag;
  2192. tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
  2193. if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
  2194. rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
  2195. } else {
  2196. rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
  2197. }
  2198. return rv;
  2199. }
  2200. int
  2201. SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
  2202. {
  2203. int rv = 0;
  2204. while (attrs[0]) {
  2205. rv |= SECU_PrintCertAttribute(out, attrs[0], m, level+1);
  2206. attrs++;
  2207. }
  2208. return rv;
  2209. }
  2210. int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
  2211. SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
  2212. {
  2213. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2214. CERTCertificateRequest *cr;
  2215. int rv = SEC_ERROR_NO_MEMORY;
  2216. if (!arena)
  2217. return rv;
  2218. /* Decode certificate request */
  2219. cr = PORT_ArenaZNew(arena, CERTCertificateRequest);
  2220. if (!cr)
  2221. goto loser;
  2222. cr->arena = arena;
  2223. rv = SEC_QuickDERDecodeItem(arena, cr,
  2224. SEC_ASN1_GET(CERT_CertificateRequestTemplate), der);
  2225. if (rv)
  2226. goto loser;
  2227. /* Pretty print it out */
  2228. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2229. SECU_PrintInteger(out, &cr->version, "Version", level+1);
  2230. SECU_PrintName(out, &cr->subject, "Subject", level+1);
  2231. secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
  2232. "Subject Public Key Info", level+1);
  2233. if (cr->attributes)
  2234. SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level+1);
  2235. rv = 0;
  2236. loser:
  2237. PORT_FreeArena(arena, PR_FALSE);
  2238. return rv;
  2239. }
  2240. int
  2241. SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
  2242. {
  2243. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2244. CERTCertificate *c;
  2245. int rv = SEC_ERROR_NO_MEMORY;
  2246. int iv;
  2247. if (!arena)
  2248. return rv;
  2249. /* Decode certificate */
  2250. c = PORT_ArenaZNew(arena, CERTCertificate);
  2251. if (!c)
  2252. goto loser;
  2253. c->arena = arena;
  2254. rv = SEC_ASN1DecodeItem(arena, c,
  2255. SEC_ASN1_GET(CERT_CertificateTemplate), der);
  2256. if (rv) {
  2257. SECU_Indent(out, level);
  2258. SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
  2259. SECU_PrintAny(out, der, "Raw", level);
  2260. goto loser;
  2261. }
  2262. /* Pretty print it out */
  2263. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2264. iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
  2265. SECU_Indent(out, level+1); fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
  2266. SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level+1);
  2267. SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level+1);
  2268. SECU_PrintName(out, &c->issuer, "Issuer", level+1);
  2269. secu_PrintValidity(out, &c->validity, "Validity", level+1);
  2270. SECU_PrintName(out, &c->subject, "Subject", level+1);
  2271. secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
  2272. "Subject Public Key Info", level+1);
  2273. if (c->issuerID.data)
  2274. secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level+1);
  2275. if (c->subjectID.data)
  2276. secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level+1);
  2277. SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level+1);
  2278. loser:
  2279. PORT_FreeArena(arena, PR_FALSE);
  2280. return rv;
  2281. }
  2282. int
  2283. SECU_PrintRSAPublicKey(FILE *out, SECItem *der, char *m, int level)
  2284. {
  2285. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2286. SECKEYPublicKey key;
  2287. int rv = SEC_ERROR_NO_MEMORY;
  2288. if (!arena)
  2289. return rv;
  2290. PORT_Memset(&key, 0, sizeof(key));
  2291. rv = SEC_ASN1DecodeItem(arena, &key,
  2292. SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), der);
  2293. if (!rv) {
  2294. /* Pretty print it out */
  2295. secu_PrintRSAPublicKey(out, &key, m, level);
  2296. }
  2297. PORT_FreeArena(arena, PR_FALSE);
  2298. return rv;
  2299. }
  2300. int
  2301. SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
  2302. {
  2303. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2304. int rv = SEC_ERROR_NO_MEMORY;
  2305. CERTSubjectPublicKeyInfo spki;
  2306. if (!arena)
  2307. return rv;
  2308. PORT_Memset(&spki, 0, sizeof spki);
  2309. rv = SEC_ASN1DecodeItem(arena, &spki,
  2310. SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate),
  2311. der);
  2312. if (!rv) {
  2313. if (m && *m) {
  2314. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2315. }
  2316. secu_PrintSubjectPublicKeyInfo(out, arena, &spki,
  2317. "Subject Public Key Info", level+1);
  2318. }
  2319. PORT_FreeArena(arena, PR_FALSE);
  2320. return rv;
  2321. }
  2322. #ifdef HAVE_EPV_TEMPLATE
  2323. int
  2324. SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
  2325. {
  2326. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2327. SECKEYEncryptedPrivateKeyInfo key;
  2328. int rv = SEC_ERROR_NO_MEMORY;
  2329. if (!arena)
  2330. return rv;
  2331. PORT_Memset(&key, 0, sizeof(key));
  2332. rv = SEC_ASN1DecodeItem(arena, &key,
  2333. SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), der);
  2334. if (rv)
  2335. goto loser;
  2336. /* Pretty print it out */
  2337. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2338. SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
  2339. level+1);
  2340. SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level+1);
  2341. loser:
  2342. PORT_FreeArena(arena, PR_TRUE);
  2343. return rv;
  2344. }
  2345. #endif
  2346. int
  2347. SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
  2348. {
  2349. unsigned char fingerprint[20];
  2350. char *fpStr = NULL;
  2351. int err = PORT_GetError();
  2352. SECStatus rv;
  2353. SECItem fpItem;
  2354. /* print MD5 fingerprint */
  2355. memset(fingerprint, 0, sizeof fingerprint);
  2356. rv = PK11_HashBuf(SEC_OID_MD5,fingerprint, derCert->data, derCert->len);
  2357. fpItem.data = fingerprint;
  2358. fpItem.len = MD5_LENGTH;
  2359. fpStr = CERT_Hexify(&fpItem, 1);
  2360. SECU_Indent(out, level); fprintf(out, "%s (MD5):\n", m);
  2361. SECU_Indent(out, level+1); fprintf(out, "%s\n", fpStr);
  2362. PORT_Free(fpStr);
  2363. fpStr = NULL;
  2364. if (rv != SECSuccess && !err)
  2365. err = PORT_GetError();
  2366. /* print SHA1 fingerprint */
  2367. memset(fingerprint, 0, sizeof fingerprint);
  2368. rv = PK11_HashBuf(SEC_OID_SHA1,fingerprint, derCert->data, derCert->len);
  2369. fpItem.data = fingerprint;
  2370. fpItem.len = SHA1_LENGTH;
  2371. fpStr = CERT_Hexify(&fpItem, 1);
  2372. SECU_Indent(out, level); fprintf(out, "%s (SHA1):\n", m);
  2373. SECU_Indent(out, level+1); fprintf(out, "%s\n", fpStr);
  2374. PORT_Free(fpStr);
  2375. fprintf(out, "\n");
  2376. if (err)
  2377. PORT_SetError(err);
  2378. if (err || rv != SECSuccess)
  2379. return SECFailure;
  2380. return 0;
  2381. }
  2382. /*
  2383. ** PKCS7 Support
  2384. */
  2385. /* forward declaration */
  2386. static int
  2387. secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
  2388. /*
  2389. ** secu_PrintPKCS7EncContent
  2390. ** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
  2391. */
  2392. static void
  2393. secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
  2394. char *m, int level)
  2395. {
  2396. if (src->contentTypeTag == NULL)
  2397. src->contentTypeTag = SECOID_FindOID(&(src->contentType));
  2398. SECU_Indent(out, level);
  2399. fprintf(out, "%s:\n", m);
  2400. SECU_Indent(out, level + 1);
  2401. fprintf(out, "Content Type: %s\n",
  2402. (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
  2403. : "Unknown");
  2404. SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
  2405. "Content Encryption Algorithm", level+1);
  2406. SECU_PrintAsHex(out, &(src->encContent),
  2407. "Encrypted Content", level+1);
  2408. }
  2409. /*
  2410. ** secu_PrintRecipientInfo
  2411. ** Prints a PKCS7RecipientInfo type
  2412. */
  2413. static void
  2414. secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
  2415. int level)
  2416. {
  2417. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2418. SECU_PrintInteger(out, &(info->version), "Version", level + 1);
  2419. SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
  2420. level + 1);
  2421. SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
  2422. "Serial Number", level + 1);
  2423. /* Parse and display encrypted key */
  2424. SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
  2425. "Key Encryption Algorithm", level + 1);
  2426. SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
  2427. }
  2428. /*
  2429. ** secu_PrintSignerInfo
  2430. ** Prints a PKCS7SingerInfo type
  2431. */
  2432. static void
  2433. secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
  2434. {
  2435. SEC_PKCS7Attribute *attr;
  2436. int iv;
  2437. char om[100];
  2438. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2439. SECU_PrintInteger(out, &(info->version), "Version", level + 1);
  2440. SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
  2441. level + 1);
  2442. SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
  2443. "Serial Number", level + 1);
  2444. SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
  2445. level + 1);
  2446. if (info->authAttr != NULL) {
  2447. SECU_Indent(out, level + 1);
  2448. fprintf(out, "Authenticated Attributes:\n");
  2449. iv = 0;
  2450. while ((attr = info->authAttr[iv++]) != NULL) {
  2451. sprintf(om, "Attribute (%d)", iv);
  2452. secu_PrintAttribute(out, attr, om, level + 2);
  2453. }
  2454. }
  2455. /* Parse and display signature */
  2456. SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
  2457. "Digest Encryption Algorithm", level + 1);
  2458. SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
  2459. if (info->unAuthAttr != NULL) {
  2460. SECU_Indent(out, level + 1);
  2461. fprintf(out, "Unauthenticated Attributes:\n");
  2462. iv = 0;
  2463. while ((attr = info->unAuthAttr[iv++]) != NULL) {
  2464. sprintf(om, "Attribute (%x)", iv);
  2465. secu_PrintAttribute(out, attr, om, level + 2);
  2466. }
  2467. }
  2468. }
  2469. /* callers of this function must make sure that the CERTSignedCrl
  2470. from which they are extracting the CERTCrl has been fully-decoded.
  2471. Otherwise it will not have the entries even though the CRL may have
  2472. some */
  2473. void
  2474. SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
  2475. {
  2476. CERTCrlEntry *entry;
  2477. int iv;
  2478. char om[100];
  2479. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2480. /* version is optional */
  2481. iv = crl->version.len ? DER_GetInteger(&crl->version) : 0;
  2482. SECU_Indent(out, level+1);
  2483. fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
  2484. SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
  2485. level + 1);
  2486. SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
  2487. SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
  2488. if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
  2489. SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
  2490. if (crl->entries != NULL) {
  2491. iv = 0;
  2492. while ((entry = crl->entries[iv++]) != NULL) {
  2493. sprintf(om, "Entry (%x):\n", iv);
  2494. SECU_Indent(out, level + 1); fprintf(out, om);
  2495. SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
  2496. level + 2);
  2497. SECU_PrintTimeChoice(out, &(entry->revocationDate),
  2498. "Revocation Date", level + 2);
  2499. SECU_PrintExtensions(out, entry->extensions,
  2500. "Entry Extensions", level + 2);
  2501. }
  2502. }
  2503. SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
  2504. }
  2505. /*
  2506. ** secu_PrintPKCS7Signed
  2507. ** Pretty print a PKCS7 signed data type (up to version 1).
  2508. */
  2509. static int
  2510. secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
  2511. const char *m, int level)
  2512. {
  2513. SECAlgorithmID *digAlg; /* digest algorithms */
  2514. SECItem *aCert; /* certificate */
  2515. CERTSignedCrl *aCrl; /* certificate revocation list */
  2516. SEC_PKCS7SignerInfo *sigInfo; /* signer information */
  2517. int rv, iv;
  2518. char om[100];
  2519. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2520. SECU_PrintInteger(out, &(src->version), "Version", level + 1);
  2521. /* Parse and list digest algorithms (if any) */
  2522. if (src->digestAlgorithms != NULL) {
  2523. SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
  2524. iv = 0;
  2525. while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
  2526. sprintf(om, "Digest Algorithm (%x)", iv);
  2527. SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
  2528. }
  2529. }
  2530. /* Now for the content */
  2531. rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
  2532. "Content Information", level + 1);
  2533. if (rv != 0)
  2534. return rv;
  2535. /* Parse and list certificates (if any) */
  2536. if (src->rawCerts != NULL) {
  2537. SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
  2538. iv = 0;
  2539. while ((aCert = src->rawCerts[iv++]) != NULL) {
  2540. sprintf(om, "Certificate (%x)", iv);
  2541. rv = SECU_PrintSignedData(out, aCert, om, level + 2,
  2542. SECU_PrintCertificate);
  2543. if (rv)
  2544. return rv;
  2545. }
  2546. }
  2547. /* Parse and list CRL's (if any) */
  2548. if (src->crls != NULL) {
  2549. SECU_Indent(out, level + 1);
  2550. fprintf(out, "Signed Revocation Lists:\n");
  2551. iv = 0;
  2552. while ((aCrl = src->crls[iv++]) != NULL) {
  2553. sprintf(om, "Signed Revocation List (%x)", iv);
  2554. SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
  2555. SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
  2556. "Signature Algorithm", level+3);
  2557. DER_ConvertBitString(&aCrl->signatureWrap.signature);
  2558. SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
  2559. level+3);
  2560. SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
  2561. level + 3);
  2562. }
  2563. }
  2564. /* Parse and list signatures (if any) */
  2565. if (src->signerInfos != NULL) {
  2566. SECU_Indent(out, level + 1);
  2567. fprintf(out, "Signer Information List:\n");
  2568. iv = 0;
  2569. while ((sigInfo = src->signerInfos[iv++]) != NULL) {
  2570. sprintf(om, "Signer Information (%x)", iv);
  2571. secu_PrintSignerInfo(out, sigInfo, om, level + 2);
  2572. }
  2573. }
  2574. return 0;
  2575. }
  2576. /*
  2577. ** secu_PrintPKCS7Enveloped
  2578. ** Pretty print a PKCS7 enveloped data type (up to version 1).
  2579. */
  2580. static void
  2581. secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
  2582. const char *m, int level)
  2583. {
  2584. SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
  2585. int iv;
  2586. char om[100];
  2587. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2588. SECU_PrintInteger(out, &(src->version), "Version", level + 1);
  2589. /* Parse and list recipients (this is not optional) */
  2590. if (src->recipientInfos != NULL) {
  2591. SECU_Indent(out, level + 1);
  2592. fprintf(out, "Recipient Information List:\n");
  2593. iv = 0;
  2594. while ((recInfo = src->recipientInfos[iv++]) != NULL) {
  2595. sprintf(om, "Recipient Information (%x)", iv);
  2596. secu_PrintRecipientInfo(out, recInfo, om, level + 2);
  2597. }
  2598. }
  2599. secu_PrintPKCS7EncContent(out, &src->encContentInfo,
  2600. "Encrypted Content Information", level + 1);
  2601. }
  2602. /*
  2603. ** secu_PrintPKCS7SignedEnveloped
  2604. ** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
  2605. */
  2606. static int
  2607. secu_PrintPKCS7SignedAndEnveloped(FILE *out,
  2608. SEC_PKCS7SignedAndEnvelopedData *src,
  2609. const char *m, int level)
  2610. {
  2611. SECAlgorithmID *digAlg; /* pointer for digest algorithms */
  2612. SECItem *aCert; /* pointer for certificate */
  2613. CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
  2614. SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
  2615. SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
  2616. int rv, iv;
  2617. char om[100];
  2618. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2619. SECU_PrintInteger(out, &(src->version), "Version", level + 1);
  2620. /* Parse and list recipients (this is not optional) */
  2621. if (src->recipientInfos != NULL) {
  2622. SECU_Indent(out, level + 1);
  2623. fprintf(out, "Recipient Information List:\n");
  2624. iv = 0;
  2625. while ((recInfo = src->recipientInfos[iv++]) != NULL) {
  2626. sprintf(om, "Recipient Information (%x)", iv);
  2627. secu_PrintRecipientInfo(out, recInfo, om, level + 2);
  2628. }
  2629. }
  2630. /* Parse and list digest algorithms (if any) */
  2631. if (src->digestAlgorithms != NULL) {
  2632. SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
  2633. iv = 0;
  2634. while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
  2635. sprintf(om, "Digest Algorithm (%x)", iv);
  2636. SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
  2637. }
  2638. }
  2639. secu_PrintPKCS7EncContent(out, &src->encContentInfo,
  2640. "Encrypted Content Information", level + 1);
  2641. /* Parse and list certificates (if any) */
  2642. if (src->rawCerts != NULL) {
  2643. SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
  2644. iv = 0;
  2645. while ((aCert = src->rawCerts[iv++]) != NULL) {
  2646. sprintf(om, "Certificate (%x)", iv);
  2647. rv = SECU_PrintSignedData(out, aCert, om, level + 2,
  2648. SECU_PrintCertificate);
  2649. if (rv)
  2650. return rv;
  2651. }
  2652. }
  2653. /* Parse and list CRL's (if any) */
  2654. if (src->crls != NULL) {
  2655. SECU_Indent(out, level + 1);
  2656. fprintf(out, "Signed Revocation Lists:\n");
  2657. iv = 0;
  2658. while ((aCrl = src->crls[iv++]) != NULL) {
  2659. sprintf(om, "Signed Revocation List (%x)", iv);
  2660. SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
  2661. SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
  2662. "Signature Algorithm", level+3);
  2663. DER_ConvertBitString(&aCrl->signatureWrap.signature);
  2664. SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
  2665. level+3);
  2666. SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
  2667. level + 3);
  2668. }
  2669. }
  2670. /* Parse and list signatures (if any) */
  2671. if (src->signerInfos != NULL) {
  2672. SECU_Indent(out, level + 1);
  2673. fprintf(out, "Signer Information List:\n");
  2674. iv = 0;
  2675. while ((sigInfo = src->signerInfos[iv++]) != NULL) {
  2676. sprintf(om, "Signer Information (%x)", iv);
  2677. secu_PrintSignerInfo(out, sigInfo, om, level + 2);
  2678. }
  2679. }
  2680. return 0;
  2681. }
  2682. int
  2683. SECU_PrintCrl (FILE *out, SECItem *der, char *m, int level)
  2684. {
  2685. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2686. CERTCrl *c = NULL;
  2687. int rv = SEC_ERROR_NO_MEMORY;
  2688. if (!arena)
  2689. return rv;
  2690. do {
  2691. /* Decode CRL */
  2692. c = PORT_ArenaZNew(arena, CERTCrl);
  2693. if (!c)
  2694. break;
  2695. rv = SEC_QuickDERDecodeItem(arena, c, SEC_ASN1_GET(CERT_CrlTemplate), der);
  2696. if (rv != SECSuccess)
  2697. break;
  2698. SECU_PrintCRLInfo (out, c, m, level);
  2699. } while (0);
  2700. PORT_FreeArena (arena, PR_FALSE);
  2701. return rv;
  2702. }
  2703. /*
  2704. ** secu_PrintPKCS7Encrypted
  2705. ** Pretty print a PKCS7 encrypted data type (up to version 1).
  2706. */
  2707. static void
  2708. secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
  2709. const char *m, int level)
  2710. {
  2711. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2712. SECU_PrintInteger(out, &(src->version), "Version", level + 1);
  2713. secu_PrintPKCS7EncContent(out, &src->encContentInfo,
  2714. "Encrypted Content Information", level + 1);
  2715. }
  2716. /*
  2717. ** secu_PrintPKCS7Digested
  2718. ** Pretty print a PKCS7 digested data type (up to version 1).
  2719. */
  2720. static void
  2721. secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
  2722. const char *m, int level)
  2723. {
  2724. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2725. SECU_PrintInteger(out, &(src->version), "Version", level + 1);
  2726. SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
  2727. level + 1);
  2728. secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
  2729. level + 1);
  2730. SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
  2731. }
  2732. /*
  2733. ** secu_PrintPKCS7ContentInfo
  2734. ** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
  2735. ** appropriate function
  2736. */
  2737. static int
  2738. secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
  2739. char *m, int level)
  2740. {
  2741. const char *desc;
  2742. SECOidTag kind;
  2743. int rv;
  2744. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2745. level++;
  2746. if (src->contentTypeTag == NULL)
  2747. src->contentTypeTag = SECOID_FindOID(&(src->contentType));
  2748. if (src->contentTypeTag == NULL) {
  2749. desc = "Unknown";
  2750. kind = SEC_OID_PKCS7_DATA;
  2751. } else {
  2752. desc = src->contentTypeTag->desc;
  2753. kind = src->contentTypeTag->offset;
  2754. }
  2755. if (src->content.data == NULL) {
  2756. SECU_Indent(out, level); fprintf(out, "%s:\n", desc);
  2757. level++;
  2758. SECU_Indent(out, level); fprintf(out, "<no content>\n");
  2759. return 0;
  2760. }
  2761. rv = 0;
  2762. switch (kind) {
  2763. case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
  2764. rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
  2765. break;
  2766. case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
  2767. secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
  2768. break;
  2769. case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
  2770. rv = secu_PrintPKCS7SignedAndEnveloped(out,
  2771. src->content.signedAndEnvelopedData,
  2772. desc, level);
  2773. break;
  2774. case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
  2775. secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
  2776. break;
  2777. case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
  2778. secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
  2779. break;
  2780. default:
  2781. SECU_PrintAsHex(out, src->content.data, desc, level);
  2782. break;
  2783. }
  2784. return rv;
  2785. }
  2786. /*
  2787. ** SECU_PrintPKCS7ContentInfo
  2788. ** Decode and print any major PKCS7 data type (up to version 1).
  2789. */
  2790. int
  2791. SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
  2792. {
  2793. SEC_PKCS7ContentInfo *cinfo;
  2794. int rv;
  2795. cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  2796. if (cinfo != NULL) {
  2797. /* Send it to recursive parsing and printing module */
  2798. rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
  2799. SEC_PKCS7DestroyContentInfo(cinfo);
  2800. } else {
  2801. rv = -1;
  2802. }
  2803. return rv;
  2804. }
  2805. /*
  2806. ** End of PKCS7 functions
  2807. */
  2808. void
  2809. printFlags(FILE *out, unsigned int flags, int level)
  2810. {
  2811. if ( flags & CERTDB_VALID_PEER ) {
  2812. SECU_Indent(out, level); fprintf(out, "Valid Peer\n");
  2813. }
  2814. if ( flags & CERTDB_TRUSTED ) {
  2815. SECU_Indent(out, level); fprintf(out, "Trusted\n");
  2816. }
  2817. if ( flags & CERTDB_SEND_WARN ) {
  2818. SECU_Indent(out, level); fprintf(out, "Warn When Sending\n");
  2819. }
  2820. if ( flags & CERTDB_VALID_CA ) {
  2821. SECU_Indent(out, level); fprintf(out, "Valid CA\n");
  2822. }
  2823. if ( flags & CERTDB_TRUSTED_CA ) {
  2824. SECU_Indent(out, level); fprintf(out, "Trusted CA\n");
  2825. }
  2826. if ( flags & CERTDB_NS_TRUSTED_CA ) {
  2827. SECU_Indent(out, level); fprintf(out, "Netscape Trusted CA\n");
  2828. }
  2829. if ( flags & CERTDB_USER ) {
  2830. SECU_Indent(out, level); fprintf(out, "User\n");
  2831. }
  2832. if ( flags & CERTDB_TRUSTED_CLIENT_CA ) {
  2833. SECU_Indent(out, level); fprintf(out, "Trusted Client CA\n");
  2834. }
  2835. if ( flags & CERTDB_GOVT_APPROVED_CA ) {
  2836. SECU_Indent(out, level); fprintf(out, "Step-up\n");
  2837. }
  2838. }
  2839. void
  2840. SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
  2841. {
  2842. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2843. SECU_Indent(out, level+1); fprintf(out, "SSL Flags:\n");
  2844. printFlags(out, trust->sslFlags, level+2);
  2845. SECU_Indent(out, level+1); fprintf(out, "Email Flags:\n");
  2846. printFlags(out, trust->emailFlags, level+2);
  2847. SECU_Indent(out, level+1); fprintf(out, "Object Signing Flags:\n");
  2848. printFlags(out, trust->objectSigningFlags, level+2);
  2849. }
  2850. int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
  2851. int level, SECU_PPFunc inner)
  2852. {
  2853. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2854. CERTSignedData *sd;
  2855. int rv = SEC_ERROR_NO_MEMORY;
  2856. if (!arena)
  2857. return rv;
  2858. /* Strip off the signature */
  2859. sd = PORT_ArenaZNew(arena, CERTSignedData);
  2860. if (!sd)
  2861. goto loser;
  2862. rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
  2863. der);
  2864. if (rv)
  2865. goto loser;
  2866. SECU_Indent(out, level); fprintf(out, "%s:\n", m);
  2867. rv = (*inner)(out, &sd->data, "Data", level+1);
  2868. SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
  2869. level+1);
  2870. DER_ConvertBitString(&sd->signature);
  2871. SECU_PrintAsHex(out, &sd->signature, "Signature", level+1);
  2872. SECU_PrintFingerprints(out, der, "Fingerprint", level+1);
  2873. loser:
  2874. PORT_FreeArena(arena, PR_FALSE);
  2875. return rv;
  2876. }
  2877. SECStatus
  2878. SEC_PrintCertificateAndTrust(CERTCertificate *cert,
  2879. const char *label,
  2880. CERTCertTrust *trust)
  2881. {
  2882. SECStatus rv;
  2883. SECItem data;
  2884. data.data = cert->derCert.data;
  2885. data.len = cert->derCert.len;
  2886. rv = SECU_PrintSignedData(stdout, &data, label, 0,
  2887. SECU_PrintCertificate);
  2888. if (rv) {
  2889. return(SECFailure);
  2890. }
  2891. if (trust) {
  2892. SECU_PrintTrustFlags(stdout, trust,
  2893. "Certificate Trust Flags", 1);
  2894. } else if (cert->trust) {
  2895. SECU_PrintTrustFlags(stdout, cert->trust,
  2896. "Certificate Trust Flags", 1);
  2897. }
  2898. printf("\n");
  2899. return(SECSuccess);
  2900. }
  2901. SECStatus
  2902. SECU_ParseCommandLine(int argc, char **argv, char *progName,
  2903. const secuCommand *cmd)
  2904. {
  2905. PRBool found;
  2906. PLOptState *optstate;
  2907. PLOptStatus status;
  2908. char *optstring;
  2909. PLLongOpt *longopts = NULL;
  2910. int i, j;
  2911. int lcmd = 0, lopt = 0;
  2912. optstring = (char *)PORT_Alloc(cmd->numCommands + 2*cmd->numOptions+1);
  2913. if (optstring == NULL)
  2914. return SECFailure;
  2915. j = 0;
  2916. for (i=0; i<cmd->numCommands; i++) {
  2917. if (cmd->commands[i].flag) /* single character option ? */
  2918. optstring[j++] = cmd->commands[i].flag;
  2919. if (cmd->commands[i].longform)
  2920. lcmd++;
  2921. }
  2922. for (i=0; i<cmd->numOptions; i++) {
  2923. if (cmd->options[i].flag) {
  2924. optstring[j++] = cmd->options[i].flag;
  2925. if (cmd->options[i].needsArg)
  2926. optstring[j++] = ':';
  2927. }
  2928. if (cmd->options[i].longform)
  2929. lopt++;
  2930. }
  2931. optstring[j] = '\0';
  2932. if (lcmd + lopt > 0) {
  2933. longopts = PORT_NewArray(PLLongOpt, lcmd+lopt+1);
  2934. if (!longopts) {
  2935. PORT_Free(optstring);
  2936. return SECFailure;
  2937. }
  2938. j = 0;
  2939. for (i=0; j<lcmd && i<cmd->numCommands; i++) {
  2940. if (cmd->commands[i].longform) {
  2941. longopts[j].longOptName = cmd->commands[i].longform;
  2942. longopts[j].longOption = 0;
  2943. longopts[j++].valueRequired = cmd->commands[i].needsArg;
  2944. }
  2945. }
  2946. lopt += lcmd;
  2947. for (i=0; j<lopt && i<cmd->numOptions; i++) {
  2948. if (cmd->options[i].longform) {
  2949. longopts[j].longOptName = cmd->options[i].longform;
  2950. longopts[j].longOption = 0;
  2951. longopts[j++].valueRequired = cmd->options[i].needsArg;
  2952. }
  2953. }
  2954. longopts[j].longOptName = NULL;
  2955. }
  2956. optstate = PL_CreateLongOptState(argc, argv, optstring, longopts);
  2957. if (!optstate) {
  2958. PORT_Free(optstring);
  2959. PORT_Free(longopts);
  2960. return SECFailure;
  2961. }
  2962. /* Parse command line arguments */
  2963. while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
  2964. const char *optstatelong;
  2965. char option = optstate->option;
  2966. /* positional parameter, single-char option or long opt? */
  2967. if (optstate->longOptIndex == -1) {
  2968. /* not a long opt */
  2969. if (option == '\0')
  2970. continue; /* it's a positional parameter */
  2971. optstatelong = "";
  2972. } else {
  2973. /* long opt */
  2974. if (option == '\0')
  2975. option = '\377'; /* force unequal with all flags */
  2976. optstatelong = longopts[optstate->longOptIndex].longOptName;
  2977. }
  2978. found = PR_FALSE;
  2979. for (i=0; i<cmd->numCommands; i++) {
  2980. if (cmd->commands[i].flag == option ||
  2981. cmd->commands[i].longform == optstatelong) {
  2982. cmd->commands[i].activated = PR_TRUE;
  2983. if (optstate->value) {
  2984. cmd->commands[i].arg = (char *)optstate->value;
  2985. }
  2986. found = PR_TRUE;
  2987. break;
  2988. }
  2989. }
  2990. if (found)
  2991. continue;
  2992. for (i=0; i<cmd->numOptions; i++) {
  2993. if (cmd->options[i].flag == option ||
  2994. cmd->options[i].longform == optstatelong) {
  2995. cmd->options[i].activated = PR_TRUE;
  2996. if (optstate->value) {
  2997. cmd->options[i].arg = (char *)optstate->value;
  2998. } else if (cmd->options[i].needsArg) {
  2999. status = PL_OPT_BAD;
  3000. goto loser;
  3001. }
  3002. found = PR_TRUE;
  3003. break;
  3004. }
  3005. }
  3006. if (!found) {
  3007. status = PL_OPT_BAD;
  3008. break;
  3009. }
  3010. }
  3011. loser:
  3012. PL_DestroyOptState(optstate);
  3013. PORT_Free(optstring);
  3014. if (longopts)
  3015. PORT_Free(longopts);
  3016. if (status == PL_OPT_BAD)
  3017. return SECFailure;
  3018. return SECSuccess;
  3019. }
  3020. char *
  3021. SECU_GetOptionArg(const secuCommand *cmd, int optionNum)
  3022. {
  3023. if (optionNum < 0 || optionNum >= cmd->numOptions)
  3024. return NULL;
  3025. if (cmd->options[optionNum].activated)
  3026. return PL_strdup(cmd->options[optionNum].arg);
  3027. else
  3028. return NULL;
  3029. }
  3030. static char SECUErrorBuf[64];
  3031. char *
  3032. SECU_ErrorStringRaw(int16 err)
  3033. {
  3034. if (err == 0)
  3035. SECUErrorBuf[0] = '\0';
  3036. else if (err == SEC_ERROR_BAD_DATA)
  3037. sprintf(SECUErrorBuf, "Bad data");
  3038. else if (err == SEC_ERROR_BAD_DATABASE)
  3039. sprintf(SECUErrorBuf, "Problem with database");
  3040. else if (err == SEC_ERROR_BAD_DER)
  3041. sprintf(SECUErrorBuf, "Problem with DER");
  3042. else if (err == SEC_ERROR_BAD_KEY)
  3043. sprintf(SECUErrorBuf, "Problem with key");
  3044. else if (err == SEC_ERROR_BAD_PASSWORD)
  3045. sprintf(SECUErrorBuf, "Incorrect password");
  3046. else if (err == SEC_ERROR_BAD_SIGNATURE)
  3047. sprintf(SECUErrorBuf, "Bad signature");
  3048. else if (err == SEC_ERROR_EXPIRED_CERTIFICATE)
  3049. sprintf(SECUErrorBuf, "Expired certificate");
  3050. else if (err == SEC_ERROR_EXTENSION_VALUE_INVALID)
  3051. sprintf(SECUErrorBuf, "Invalid extension value");
  3052. else if (err == SEC_ERROR_INPUT_LEN)
  3053. sprintf(SECUErrorBuf, "Problem with input length");
  3054. else if (err == SEC_ERROR_INVALID_ALGORITHM)
  3055. sprintf(SECUErrorBuf, "Invalid algorithm");
  3056. else if (err == SEC_ERROR_INVALID_ARGS)
  3057. sprintf(SECUErrorBuf, "Invalid arguments");
  3058. else if (err == SEC_ERROR_INVALID_AVA)
  3059. sprintf(SECUErrorBuf, "Invalid AVA");
  3060. else if (err == SEC_ERROR_INVALID_TIME)
  3061. sprintf(SECUErrorBuf, "Invalid time");
  3062. else if (err == SEC_ERROR_IO)
  3063. sprintf(SECUErrorBuf, "Security I/O error");
  3064. else if (err == SEC_ERROR_LIBRARY_FAILURE)
  3065. sprintf(SECUErrorBuf, "Library failure");
  3066. else if (err == SEC_ERROR_NO_MEMORY)
  3067. sprintf(SECUErrorBuf, "Out of memory");
  3068. else if (err == SEC_ERROR_OLD_CRL)
  3069. sprintf(SECUErrorBuf, "CRL is older than the current one");
  3070. else if (err == SEC_ERROR_OUTPUT_LEN)
  3071. sprintf(SECUErrorBuf, "Problem with output length");
  3072. else if (err == SEC_ERROR_UNKNOWN_ISSUER)
  3073. sprintf(SECUErrorBuf, "Unknown issuer");
  3074. else if (err == SEC_ERROR_UNTRUSTED_CERT)
  3075. sprintf(SECUErrorBuf, "Untrusted certificate");
  3076. else if (err == SEC_ERROR_UNTRUSTED_ISSUER)
  3077. sprintf(SECUErrorBuf, "Untrusted issuer");
  3078. else if (err == SSL_ERROR_BAD_CERTIFICATE)
  3079. sprintf(SECUErrorBuf, "Bad certificate");
  3080. else if (err == SSL_ERROR_BAD_CLIENT)
  3081. sprintf(SECUErrorBuf, "Bad client");
  3082. else if (err == SSL_ERROR_BAD_SERVER)
  3083. sprintf(SECUErrorBuf, "Bad server");
  3084. else if (err == SSL_ERROR_EXPORT_ONLY_SERVER)
  3085. sprintf(SECUErrorBuf, "Export only server");
  3086. else if (err == SSL_ERROR_NO_CERTIFICATE)
  3087. sprintf(SECUErrorBuf, "No certificate");
  3088. else if (err == SSL_ERROR_NO_CYPHER_OVERLAP)
  3089. sprintf(SECUErrorBuf, "No cypher overlap");
  3090. else if (err == SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE)
  3091. sprintf(SECUErrorBuf, "Unsupported certificate type");
  3092. else if (err == SSL_ERROR_UNSUPPORTED_VERSION)
  3093. sprintf(SECUErrorBuf, "Unsupported version");
  3094. else if (err == SSL_ERROR_US_ONLY_SERVER)
  3095. sprintf(SECUErrorBuf, "U.S. only server");
  3096. else if (err == PR_IO_ERROR)
  3097. sprintf(SECUErrorBuf, "I/O error");
  3098. else if (err == SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE)
  3099. sprintf (SECUErrorBuf, "Expired Issuer Certificate");
  3100. else if (err == SEC_ERROR_REVOKED_CERTIFICATE)
  3101. sprintf (SECUErrorBuf, "Revoked certificate");
  3102. else if (err == SEC_ERROR_NO_KEY)
  3103. sprintf (SECUErrorBuf, "No private key in database for this cert");
  3104. else if (err == SEC_ERROR_CERT_NOT_VALID)
  3105. sprintf (SECUErrorBuf, "Certificate is not valid");
  3106. else if (err == SEC_ERROR_EXTENSION_NOT_FOUND)
  3107. sprintf (SECUErrorBuf, "Certificate extension was not found");
  3108. else if (err == SEC_ERROR_EXTENSION_VALUE_INVALID)
  3109. sprintf (SECUErrorBuf, "Certificate extension value invalid");
  3110. else if (err == SEC_ERROR_CA_CERT_INVALID)
  3111. sprintf (SECUErrorBuf, "Issuer certificate is invalid");
  3112. else if (err == SEC_ERROR_CERT_USAGES_INVALID)
  3113. sprintf (SECUErrorBuf, "Certificate usages is invalid");
  3114. else if (err == SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION)
  3115. sprintf (SECUErrorBuf, "Certificate has unknown critical extension");
  3116. else if (err == SEC_ERROR_PKCS7_BAD_SIGNATURE)
  3117. sprintf (SECUErrorBuf, "Bad PKCS7 signature");
  3118. else if (err == SEC_ERROR_INADEQUATE_KEY_USAGE)
  3119. sprintf (SECUErrorBuf, "Certificate not approved for this operation");
  3120. else if (err == SEC_ERROR_INADEQUATE_CERT_TYPE)
  3121. sprintf (SECUErrorBuf, "Certificate not approved for this operation");
  3122. return SECUErrorBuf;
  3123. }
  3124. char *
  3125. SECU_ErrorString(int16 err)
  3126. {
  3127. char *error_string;
  3128. *SECUErrorBuf = 0;
  3129. SECU_ErrorStringRaw (err);
  3130. if (*SECUErrorBuf == 0) {
  3131. error_string = SECU_GetString(err);
  3132. if (error_string == NULL || *error_string == '\0')
  3133. sprintf(SECUErrorBuf, "No error string found for %d.", err);
  3134. else
  3135. return error_string;
  3136. }
  3137. return SECUErrorBuf;
  3138. }
  3139. void
  3140. SECU_PrintPRandOSError(char *progName)
  3141. {
  3142. char buffer[513];
  3143. PRInt32 errLen = PR_GetErrorTextLength();
  3144. if (errLen > 0 && errLen < sizeof buffer) {
  3145. PR_GetErrorText(buffer);
  3146. }
  3147. SECU_PrintError(progName, "function failed");
  3148. if (errLen > 0 && errLen < sizeof buffer) {
  3149. PR_fprintf(PR_STDERR, "\t%s\n", buffer);
  3150. }
  3151. }
  3152. static char *
  3153. bestCertName(CERTCertificate *cert) {
  3154. if (cert->nickname) {
  3155. return cert->nickname;
  3156. }
  3157. if (cert->emailAddr && cert->emailAddr[0]) {
  3158. return cert->emailAddr;
  3159. }
  3160. return cert->subjectName;
  3161. }
  3162. void
  3163. SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
  3164. CERTCertificate *cert, PRBool checksig,
  3165. SECCertificateUsage certUsage, void *pinArg, PRBool verbose,
  3166. PRTime datetime)
  3167. {
  3168. CERTVerifyLog log;
  3169. CERTVerifyLogNode *node;
  3170. PRErrorCode err = PORT_GetError();
  3171. log.arena = PORT_NewArena(512);
  3172. log.head = log.tail = NULL;
  3173. log.count = 0;
  3174. CERT_VerifyCertificate(handle, cert, checksig, certUsage, datetime, pinArg, &log, NULL);
  3175. SECU_displayVerifyLog(outfile, &log, verbose);
  3176. for (node = log.head; node; node = node->next) {
  3177. if (node->cert)
  3178. CERT_DestroyCertificate(node->cert);
  3179. }
  3180. PORT_FreeArena(log.arena, PR_FALSE);
  3181. PORT_SetError(err); /* restore original error code */
  3182. }
  3183. void
  3184. SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
  3185. PRBool verbose)
  3186. {
  3187. CERTVerifyLogNode *node = NULL;
  3188. unsigned int depth = (unsigned int)-1;
  3189. unsigned int flags = 0;
  3190. char * errstr = NULL;
  3191. if (log->count > 0) {
  3192. fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
  3193. for (node = log->head; node; node = node->next) {
  3194. if (depth != node->depth) {
  3195. depth = node->depth;
  3196. fprintf(outfile,"CERT %d. %s %s:\n", depth,
  3197. bestCertName(node->cert),
  3198. depth ? "[Certificate Authority]": "");
  3199. if (verbose) {
  3200. const char * emailAddr;
  3201. emailAddr = CERT_GetFirstEmailAddress(node->cert);
  3202. if (emailAddr) {
  3203. fprintf(outfile,"Email Address(es): ");
  3204. do {
  3205. fprintf(outfile, "%s\n", emailAddr);
  3206. emailAddr = CERT_GetNextEmailAddress(node->cert,
  3207. emailAddr);
  3208. } while (emailAddr);
  3209. }
  3210. }
  3211. }
  3212. fprintf(outfile," ERROR %ld: %s\n", node->error,
  3213. SECU_Strerror(node->error));
  3214. errstr = NULL;
  3215. switch (node->error) {
  3216. case SEC_ERROR_INADEQUATE_KEY_USAGE:
  3217. flags = (unsigned int)node->arg;
  3218. switch (flags) {
  3219. case KU_DIGITAL_SIGNATURE:
  3220. errstr = "Cert cannot sign.";
  3221. break;
  3222. case KU_KEY_ENCIPHERMENT:
  3223. errstr = "Cert cannot encrypt.";
  3224. break;
  3225. case KU_KEY_CERT_SIGN:
  3226. errstr = "Cert cannot sign other certs.";
  3227. break;
  3228. default:
  3229. errstr = "[unknown usage].";
  3230. break;
  3231. }
  3232. case SEC_ERROR_INADEQUATE_CERT_TYPE:
  3233. flags = (unsigned int)node->arg;
  3234. switch (flags) {
  3235. case NS_CERT_TYPE_SSL_CLIENT:
  3236. case NS_CERT_TYPE_SSL_SERVER:
  3237. errstr = "Cert cannot be used for SSL.";
  3238. break;
  3239. case NS_CERT_TYPE_SSL_CA:
  3240. errstr = "Cert cannot be used as an SSL CA.";
  3241. break;
  3242. case NS_CERT_TYPE_EMAIL:
  3243. errstr = "Cert cannot be used for SMIME.";
  3244. break;
  3245. case NS_CERT_TYPE_EMAIL_CA:
  3246. errstr = "Cert cannot be used as an SMIME CA.";
  3247. break;
  3248. case NS_CERT_TYPE_OBJECT_SIGNING:
  3249. errstr = "Cert cannot be used for object signing.";
  3250. break;
  3251. case NS_CERT_TYPE_OBJECT_SIGNING_CA:
  3252. errstr = "Cert cannot be used as an object signing CA.";
  3253. break;
  3254. default:
  3255. errstr = "[unknown usage].";
  3256. break;
  3257. }
  3258. case SEC_ERROR_UNKNOWN_ISSUER:
  3259. case SEC_ERROR_UNTRUSTED_ISSUER:
  3260. case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
  3261. errstr = node->cert->issuerName;
  3262. break;
  3263. default:
  3264. break;
  3265. }
  3266. if (errstr) {
  3267. fprintf(stderr," %s\n",errstr);
  3268. }
  3269. }
  3270. }
  3271. }
  3272. void
  3273. SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
  3274. CERTCertificate *cert, PRBool checksig,
  3275. SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
  3276. {
  3277. SECU_printCertProblemsOnDate(outfile, handle, cert, checksig,
  3278. certUsage, pinArg, verbose, PR_Now());
  3279. }
  3280. SECOidTag
  3281. SECU_StringToSignatureAlgTag(const char *alg)
  3282. {
  3283. SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
  3284. if (alg) {
  3285. if (!PL_strcmp(alg, "MD2")) {
  3286. hashAlgTag = SEC_OID_MD2;
  3287. } else if (!PL_strcmp(alg, "MD4")) {
  3288. hashAlgTag = SEC_OID_MD4;
  3289. } else if (!PL_strcmp(alg, "MD5")) {
  3290. hashAlgTag = SEC_OID_MD5;
  3291. } else if (!PL_strcmp(alg, "SHA1")) {
  3292. hashAlgTag = SEC_OID_SHA1;
  3293. } else if (!PL_strcmp(alg, "SHA256")) {
  3294. hashAlgTag = SEC_OID_SHA256;
  3295. } else if (!PL_strcmp(alg, "SHA384")) {
  3296. hashAlgTag = SEC_OID_SHA384;
  3297. } else if (!PL_strcmp(alg, "SHA512")) {
  3298. hashAlgTag = SEC_OID_SHA512;
  3299. }
  3300. }
  3301. return hashAlgTag;
  3302. }
  3303. SECStatus
  3304. SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
  3305. PRBool ascii, char *url)
  3306. {
  3307. PORT_Assert(derCrl != NULL);
  3308. if (!derCrl) {
  3309. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3310. return SECFailure;
  3311. }
  3312. if (outFile != NULL) {
  3313. if (ascii) {
  3314. PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER,
  3315. BTOA_DataToAscii(derCrl->data, derCrl->len),
  3316. NS_CRL_TRAILER);
  3317. } else {
  3318. if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
  3319. return SECFailure;
  3320. }
  3321. }
  3322. }
  3323. if (slot) {
  3324. CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
  3325. SEC_CRL_TYPE, NULL, 0, NULL, 0);
  3326. if (newCrl != NULL) {
  3327. SEC_DestroyCrl(newCrl);
  3328. return SECSuccess;
  3329. }
  3330. return SECFailure;
  3331. }
  3332. if (!outFile && !slot) {
  3333. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3334. return SECFailure;
  3335. }
  3336. return SECSuccess;
  3337. }
  3338. SECStatus
  3339. SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
  3340. SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
  3341. {
  3342. SECItem der;
  3343. SECKEYPrivateKey *caPrivateKey = NULL;
  3344. SECStatus rv;
  3345. PRArenaPool *arena;
  3346. SECOidTag algID;
  3347. void *dummy;
  3348. PORT_Assert(issuer != NULL && signCrl != NULL);
  3349. if (!issuer || !signCrl) {
  3350. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3351. return SECFailure;
  3352. }
  3353. arena = signCrl->arena;
  3354. caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL);
  3355. if (caPrivateKey == NULL) {
  3356. *resCode = noKeyFound;
  3357. return SECFailure;
  3358. }
  3359. algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, hashAlgTag);
  3360. if (algID == SEC_OID_UNKNOWN) {
  3361. *resCode = noSignatureMatch;
  3362. rv = SECFailure;
  3363. goto done;
  3364. }
  3365. if (!signCrl->crl.signatureAlg.parameters.data) {
  3366. rv = SECOID_SetAlgorithmID(arena, &signCrl->crl.signatureAlg, algID, 0);
  3367. if (rv != SECSuccess) {
  3368. *resCode = failToEncode;
  3369. goto done;
  3370. }
  3371. }
  3372. der.len = 0;
  3373. der.data = NULL;
  3374. dummy = SEC_ASN1EncodeItem(arena, &der, &signCrl->crl,
  3375. SEC_ASN1_GET(CERT_CrlTemplate));
  3376. if (!dummy) {
  3377. *resCode = failToEncode;
  3378. rv = SECFailure;
  3379. goto done;
  3380. }
  3381. rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
  3382. der.data, der.len, caPrivateKey, algID);
  3383. if (rv != SECSuccess) {
  3384. *resCode = failToSign;
  3385. goto done;
  3386. }
  3387. signCrl->derCrl = PORT_ArenaZNew(arena, SECItem);
  3388. if (signCrl->derCrl == NULL) {
  3389. *resCode = noMem;
  3390. PORT_SetError(SEC_ERROR_NO_MEMORY);
  3391. rv = SECFailure;
  3392. goto done;
  3393. }
  3394. signCrl->derCrl->len = 0;
  3395. signCrl->derCrl->data = NULL;
  3396. dummy = SEC_ASN1EncodeItem (arena, signCrl->derCrl, signCrl,
  3397. SEC_ASN1_GET(CERT_SignedCrlTemplate));
  3398. if (!dummy) {
  3399. *resCode = failToEncode;
  3400. rv = SECFailure;
  3401. goto done;
  3402. }
  3403. done:
  3404. if (caPrivateKey) {
  3405. SECKEY_DestroyPrivateKey(caPrivateKey);
  3406. }
  3407. return rv;
  3408. }
  3409. SECStatus
  3410. SECU_CopyCRL(PRArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
  3411. {
  3412. void *dummy;
  3413. SECStatus rv = SECSuccess;
  3414. SECItem der;
  3415. PORT_Assert(destArena && srcCrl && destCrl);
  3416. if (!destArena || !srcCrl || !destCrl) {
  3417. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3418. return SECFailure;
  3419. }
  3420. der.len = 0;
  3421. der.data = NULL;
  3422. dummy = SEC_ASN1EncodeItem (destArena, &der, srcCrl,
  3423. SEC_ASN1_GET(CERT_CrlTemplate));
  3424. if (!dummy) {
  3425. return SECFailure;
  3426. }
  3427. rv = SEC_QuickDERDecodeItem(destArena, destCrl,
  3428. SEC_ASN1_GET(CERT_CrlTemplate), &der);
  3429. if (rv != SECSuccess) {
  3430. return SECFailure;
  3431. }
  3432. destCrl->arena = destArena;
  3433. return rv;
  3434. }
  3435. SECStatus
  3436. SECU_DerSignDataCRL(PRArenaPool *arena, CERTSignedData *sd,
  3437. unsigned char *buf, int len, SECKEYPrivateKey *pk,
  3438. SECOidTag algID)
  3439. {
  3440. SECItem it;
  3441. SECStatus rv;
  3442. it.data = 0;
  3443. /* XXX We should probably have some asserts here to make sure the key type
  3444. * and algID match
  3445. */
  3446. /* Sign input buffer */
  3447. rv = SEC_SignData(&it, buf, len, pk, algID);
  3448. if (rv) goto loser;
  3449. /* Fill out SignedData object */
  3450. PORT_Memset(sd, 0, sizeof(sd));
  3451. sd->data.data = buf;
  3452. sd->data.len = len;
  3453. sd->signature.data = it.data;
  3454. sd->signature.len = it.len << 3; /* convert to bit string */
  3455. if (!sd->signatureAlgorithm.parameters.data) {
  3456. rv = SECOID_SetAlgorithmID(arena, &sd->signatureAlgorithm, algID, 0);
  3457. if (rv) goto loser;
  3458. }
  3459. return rv;
  3460. loser:
  3461. PORT_Free(it.data);
  3462. return rv;
  3463. }
  3464. #if 0
  3465. /* we need access to the private function cert_FindExtension for this code to work */
  3466. CERTAuthKeyID *
  3467. SECU_FindCRLAuthKeyIDExten (PRArenaPool *arena, CERTSignedCrl *scrl)
  3468. {
  3469. SECItem encodedExtenValue;
  3470. SECStatus rv;
  3471. CERTAuthKeyID *ret;
  3472. CERTCrl* crl;
  3473. if (!scrl) {
  3474. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3475. return NULL;
  3476. }
  3477. crl = &scrl->crl;
  3478. encodedExtenValue.data = NULL;
  3479. encodedExtenValue.len = 0;
  3480. rv = cert_FindExtension(crl->extensions, SEC_OID_X509_AUTH_KEY_ID,
  3481. &encodedExtenValue);
  3482. if ( rv != SECSuccess ) {
  3483. return (NULL);
  3484. }
  3485. ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue);
  3486. PORT_Free(encodedExtenValue.data);
  3487. encodedExtenValue.data = NULL;
  3488. return(ret);
  3489. }
  3490. #endif
  3491. /*
  3492. * Find the issuer of a Crl. Use the authorityKeyID if it exists.
  3493. */
  3494. CERTCertificate *
  3495. SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem* subject,
  3496. CERTAuthKeyID* authorityKeyID, PRTime validTime)
  3497. {
  3498. CERTCertificate *issuerCert = NULL;
  3499. CERTCertList *certList = NULL;
  3500. if (!subject) {
  3501. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3502. return NULL;
  3503. }
  3504. certList =
  3505. CERT_CreateSubjectCertList(NULL, dbhandle, subject,
  3506. validTime, PR_TRUE);
  3507. if (certList) {
  3508. CERTCertListNode *node = CERT_LIST_HEAD(certList);
  3509. /* XXX and authoritykeyid in the future */
  3510. while ( ! CERT_LIST_END(node, certList) ) {
  3511. CERTCertificate *cert = node->cert;
  3512. /* check cert CERTCertTrust data is allocated, check cert
  3513. usage extension, check that cert has pkey in db. Select
  3514. the first (newest) user cert */
  3515. if (cert->trust &&
  3516. CERT_CheckCertUsage(cert, KU_CRL_SIGN) == SECSuccess &&
  3517. CERT_IsUserCert(cert)) {
  3518. issuerCert = CERT_DupCertificate(cert);
  3519. break;
  3520. }
  3521. node = CERT_LIST_NEXT(node);
  3522. }
  3523. CERT_DestroyCertList(certList);
  3524. }
  3525. return(issuerCert);
  3526. }
  3527. /* Encodes and adds extensions to the CRL or CRL entries. */
  3528. SECStatus
  3529. SECU_EncodeAndAddExtensionValue(PRArenaPool *arena, void *extHandle,
  3530. void *value, PRBool criticality, int extenType,
  3531. EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
  3532. {
  3533. SECItem encodedValue;
  3534. SECStatus rv;
  3535. encodedValue.data = NULL;
  3536. encodedValue.len = 0;
  3537. do {
  3538. rv = (*EncodeValueFn)(arena, value, &encodedValue);
  3539. if (rv != SECSuccess)
  3540. break;
  3541. rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
  3542. criticality, PR_TRUE);
  3543. if (rv != SECSuccess)
  3544. break;
  3545. } while (0);
  3546. return (rv);
  3547. }
  3548. /* Caller ensures that dst is at least item->len*2+1 bytes long */
  3549. void
  3550. SECU_SECItemToHex(const SECItem * item, char * dst)
  3551. {
  3552. if (dst && item && item->data) {
  3553. unsigned char * src = item->data;
  3554. unsigned int len = item->len;
  3555. for (; len > 0; --len, dst += 2) {
  3556. sprintf(dst, "%02x", *src++);
  3557. }
  3558. *dst = '\0';
  3559. }
  3560. }
  3561. static unsigned char nibble(char c) {
  3562. c = PORT_Tolower(c);
  3563. return ( c >= '0' && c <= '9') ? c - '0' :
  3564. ( c >= 'a' && c <= 'f') ? c - 'a' +10 : -1;
  3565. }
  3566. SECStatus
  3567. SECU_SECItemHexStringToBinary(SECItem* srcdest)
  3568. {
  3569. int i;
  3570. if (!srcdest) {
  3571. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3572. return SECFailure;
  3573. }
  3574. if (srcdest->len < 4 || (srcdest->len % 2) ) {
  3575. /* too short to convert, or even number of characters */
  3576. PORT_SetError(SEC_ERROR_BAD_DATA);
  3577. return SECFailure;
  3578. }
  3579. if (PORT_Strncasecmp((const char*)srcdest->data, "0x", 2)) {
  3580. /* wrong prefix */
  3581. PORT_SetError(SEC_ERROR_BAD_DATA);
  3582. return SECFailure;
  3583. }
  3584. /* 1st pass to check for hex characters */
  3585. for (i=2; i<srcdest->len; i++) {
  3586. char c = PORT_Tolower(srcdest->data[i]);
  3587. if (! ( ( c >= '0' && c <= '9') ||
  3588. ( c >= 'a' && c <= 'f')
  3589. ) ) {
  3590. PORT_SetError(SEC_ERROR_BAD_DATA);
  3591. return SECFailure;
  3592. }
  3593. }
  3594. /* 2nd pass to convert */
  3595. for (i=2; i<srcdest->len; i+=2) {
  3596. srcdest->data[(i-2)/2] = (nibble(srcdest->data[i]) << 4) +
  3597. nibble(srcdest->data[i+1]);
  3598. }
  3599. /* adjust length */
  3600. srcdest->len -= 2;
  3601. srcdest->len /= 2;
  3602. return SECSuccess;
  3603. }