PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/security/nss/lib/cryptohi/seckey.c

http://github.com/zpao/v8monkey
C | 1961 lines | 1470 code | 283 blank | 208 comment | 288 complexity | 8f8ef2d574c41de21600325cdb364368 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD
  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 Stephen Henson <stephen.henson@gemplus.com>
  23. * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. #include "cryptohi.h"
  39. #include "keyhi.h"
  40. #include "secoid.h"
  41. #include "secitem.h"
  42. #include "secder.h"
  43. #include "base64.h"
  44. #include "secasn1.h"
  45. #include "cert.h"
  46. #include "pk11func.h"
  47. #include "secerr.h"
  48. #include "secdig.h"
  49. #include "prtime.h"
  50. #include "ec.h"
  51. #include "keyi.h"
  52. SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
  53. SEC_ASN1_MKSUB(SEC_IntegerTemplate)
  54. const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
  55. { SEC_ASN1_SEQUENCE,
  56. 0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
  57. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  58. offsetof(CERTSubjectPublicKeyInfo,algorithm),
  59. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  60. { SEC_ASN1_BIT_STRING,
  61. offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },
  62. { 0, }
  63. };
  64. const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] =
  65. {
  66. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
  67. { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) },
  68. { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) },
  69. { 0 }
  70. };
  71. const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
  72. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
  73. { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), },
  74. { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), },
  75. { 0, }
  76. };
  77. static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = {
  78. { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0,
  79. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }
  80. };
  81. /* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */
  82. const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] =
  83. {
  84. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) },
  85. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
  86. SEC_ASN1_CONTEXT_SPECIFIC | 0,
  87. offsetof(SECKEYRSAPSSParams, hashAlg),
  88. seckey_PointerToAlgorithmIDTemplate },
  89. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
  90. SEC_ASN1_CONTEXT_SPECIFIC | 1,
  91. offsetof(SECKEYRSAPSSParams, maskAlg),
  92. seckey_PointerToAlgorithmIDTemplate },
  93. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
  94. SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2,
  95. offsetof(SECKEYRSAPSSParams, saltLength),
  96. SEC_ASN1_SUB(SEC_IntegerTemplate) },
  97. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
  98. SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3,
  99. offsetof(SECKEYRSAPSSParams, trailerField),
  100. SEC_ASN1_SUB(SEC_IntegerTemplate) },
  101. { 0 }
  102. };
  103. const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
  104. { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), },
  105. { 0, }
  106. };
  107. const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
  108. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
  109. { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
  110. { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
  111. { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
  112. { 0, }
  113. };
  114. const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
  115. { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), },
  116. { 0, }
  117. };
  118. const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
  119. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
  120. { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), },
  121. { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), },
  122. /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */
  123. { SEC_ASN1_SKIP_REST },
  124. { 0, }
  125. };
  126. SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate)
  127. SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate)
  128. SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate)
  129. SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate)
  130. /*
  131. * See bugzilla bug 125359
  132. * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
  133. * all of the templates above that en/decode into integers must be converted
  134. * from ASN.1's signed integer type. This is done by marking either the
  135. * source or destination (encoding or decoding, respectively) type as
  136. * siUnsignedInteger.
  137. */
  138. static void
  139. prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
  140. {
  141. pubk->u.rsa.modulus.type = siUnsignedInteger;
  142. pubk->u.rsa.publicExponent.type = siUnsignedInteger;
  143. }
  144. static void
  145. prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
  146. {
  147. pubk->u.dsa.publicValue.type = siUnsignedInteger;
  148. }
  149. static void
  150. prepare_pqg_params_for_asn1(SECKEYPQGParams *params)
  151. {
  152. params->prime.type = siUnsignedInteger;
  153. params->subPrime.type = siUnsignedInteger;
  154. params->base.type = siUnsignedInteger;
  155. }
  156. static void
  157. prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk)
  158. {
  159. pubk->u.dh.prime.type = siUnsignedInteger;
  160. pubk->u.dh.base.type = siUnsignedInteger;
  161. pubk->u.dh.publicValue.type = siUnsignedInteger;
  162. }
  163. /* Create an RSA key pair is any slot able to do so.
  164. ** The created keys are "session" (temporary), not "token" (permanent),
  165. ** and they are "sensitive", which makes them costly to move to another token.
  166. */
  167. SECKEYPrivateKey *
  168. SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx)
  169. {
  170. SECKEYPrivateKey *privk;
  171. PK11RSAGenParams param;
  172. PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx);
  173. if (!slot) {
  174. return NULL;
  175. }
  176. param.keySizeInBits = keySizeInBits;
  177. param.pe = 65537L;
  178. privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,&param,pubk,
  179. PR_FALSE, PR_TRUE, cx);
  180. PK11_FreeSlot(slot);
  181. return(privk);
  182. }
  183. /* Create a DH key pair in any slot able to do so,
  184. ** This is a "session" (temporary), not "token" (permanent) key.
  185. ** Because of the high probability that this key will need to be moved to
  186. ** another token, and the high cost of moving "sensitive" keys, we attempt
  187. ** to create this key pair without the "sensitive" attribute, but revert to
  188. ** creating a "sensitive" key if necessary.
  189. */
  190. SECKEYPrivateKey *
  191. SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
  192. {
  193. SECKEYPrivateKey *privk;
  194. PK11SlotInfo *slot;
  195. if (!param || !param->base.data || !param->prime.data ||
  196. param->prime.len < 512/8 || param->base.len == 0 ||
  197. param->base.len > param->prime.len + 1 ||
  198. (param->base.len == 1 && param->base.data[0] == 0)) {
  199. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  200. return NULL;
  201. }
  202. slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx);
  203. if (!slot) {
  204. return NULL;
  205. }
  206. privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param,
  207. pubk, PR_FALSE, PR_FALSE, cx);
  208. if (!privk)
  209. privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param,
  210. pubk, PR_FALSE, PR_TRUE, cx);
  211. PK11_FreeSlot(slot);
  212. return(privk);
  213. }
  214. /* Create an EC key pair in any slot able to do so,
  215. ** This is a "session" (temporary), not "token" (permanent) key.
  216. ** Because of the high probability that this key will need to be moved to
  217. ** another token, and the high cost of moving "sensitive" keys, we attempt
  218. ** to create this key pair without the "sensitive" attribute, but revert to
  219. ** creating a "sensitive" key if necessary.
  220. */
  221. SECKEYPrivateKey *
  222. SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx)
  223. {
  224. SECKEYPrivateKey *privk;
  225. PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN,cx);
  226. if (!slot) {
  227. return NULL;
  228. }
  229. privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
  230. param, pubk,
  231. PK11_ATTR_SESSION | PK11_ATTR_INSENSITIVE |
  232. PK11_ATTR_PUBLIC,
  233. CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx);
  234. if (!privk)
  235. privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
  236. param, pubk,
  237. PK11_ATTR_SESSION | PK11_ATTR_SENSITIVE |
  238. PK11_ATTR_PRIVATE,
  239. CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx);
  240. PK11_FreeSlot(slot);
  241. return(privk);
  242. }
  243. void
  244. SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
  245. {
  246. if (privk) {
  247. if (privk->pkcs11Slot) {
  248. if (privk->pkcs11IsTemp) {
  249. PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID);
  250. }
  251. PK11_FreeSlot(privk->pkcs11Slot);
  252. }
  253. if (privk->arena) {
  254. PORT_FreeArena(privk->arena, PR_TRUE);
  255. }
  256. }
  257. }
  258. void
  259. SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
  260. {
  261. if (pubk) {
  262. if (pubk->pkcs11Slot) {
  263. if (!PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) {
  264. PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID);
  265. }
  266. PK11_FreeSlot(pubk->pkcs11Slot);
  267. }
  268. if (pubk->arena) {
  269. PORT_FreeArena(pubk->arena, PR_FALSE);
  270. }
  271. }
  272. }
  273. SECStatus
  274. SECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena,
  275. CERTSubjectPublicKeyInfo *to,
  276. CERTSubjectPublicKeyInfo *from)
  277. {
  278. SECStatus rv;
  279. SECItem spk;
  280. rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
  281. if (rv == SECSuccess) {
  282. /*
  283. * subjectPublicKey is a bit string, whose length is in bits.
  284. * Convert the length from bits to bytes for SECITEM_CopyItem.
  285. */
  286. spk = from->subjectPublicKey;
  287. DER_ConvertBitString(&spk);
  288. rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk);
  289. /* Set the length back to bits. */
  290. if (rv == SECSuccess) {
  291. to->subjectPublicKey.len = from->subjectPublicKey.len;
  292. }
  293. }
  294. return rv;
  295. }
  296. /* Procedure to update the pqg parameters for a cert's public key.
  297. * pqg parameters only need to be updated for DSA certificates.
  298. * The procedure uses calls to itself recursively to update a certificate
  299. * issuer's pqg parameters. Some important rules are:
  300. * - Do nothing if the cert already has PQG parameters.
  301. * - If the cert does not have PQG parameters, obtain them from the issuer.
  302. * - A valid cert chain cannot have a DSA cert without
  303. * pqg parameters that has a parent that is not a DSA cert. */
  304. static SECStatus
  305. seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count)
  306. {
  307. SECStatus rv;
  308. SECOidData *oid=NULL;
  309. int tag;
  310. CERTSubjectPublicKeyInfo * subjectSpki=NULL;
  311. CERTSubjectPublicKeyInfo * issuerSpki=NULL;
  312. CERTCertificate *issuerCert = NULL;
  313. rv = SECSuccess;
  314. /* increment cert chain length counter*/
  315. count++;
  316. /* check if cert chain length exceeds the maximum length*/
  317. if (count > CERT_MAX_CERT_CHAIN) {
  318. return SECFailure;
  319. }
  320. oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);
  321. if (oid != NULL) {
  322. tag = oid->offset;
  323. /* Check if cert has a DSA public key. If not, return
  324. * success since no PQG params need to be updated. */
  325. if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
  326. (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
  327. (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
  328. (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
  329. (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
  330. return SECSuccess;
  331. }
  332. } else {
  333. return SECFailure; /* return failure if oid is NULL */
  334. }
  335. /* if cert has PQG parameters, return success */
  336. subjectSpki=&subjectCert->subjectPublicKeyInfo;
  337. if (subjectSpki->algorithm.parameters.len != 0) {
  338. return SECSuccess;
  339. }
  340. /* check if the cert is self-signed */
  341. if (subjectCert->isRoot) {
  342. /* fail since cert is self-signed and has no pqg params. */
  343. return SECFailure;
  344. }
  345. /* get issuer cert */
  346. issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
  347. if ( ! issuerCert ) {
  348. return SECFailure;
  349. }
  350. /* if parent is not DSA, return failure since
  351. we don't allow this case. */
  352. oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
  353. if (oid != NULL) {
  354. tag = oid->offset;
  355. /* Check if issuer cert has a DSA public key. If not,
  356. * return failure. */
  357. if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
  358. (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
  359. (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
  360. (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
  361. (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
  362. rv = SECFailure;
  363. goto loser;
  364. }
  365. } else {
  366. rv = SECFailure; /* return failure if oid is NULL */
  367. goto loser;
  368. }
  369. /* at this point the subject cert has no pqg parameters and the
  370. * issuer cert has a DSA public key. Update the issuer's
  371. * pqg parameters with a recursive call to this same function. */
  372. rv = seckey_UpdateCertPQGChain(issuerCert, count);
  373. if (rv != SECSuccess) {
  374. rv = SECFailure;
  375. goto loser;
  376. }
  377. /* ensure issuer has pqg parameters */
  378. issuerSpki=&issuerCert->subjectPublicKeyInfo;
  379. if (issuerSpki->algorithm.parameters.len == 0) {
  380. rv = SECFailure;
  381. }
  382. /* if update was successful and pqg params present, then copy the
  383. * parameters to the subject cert's key. */
  384. if (rv == SECSuccess) {
  385. rv = SECITEM_CopyItem(subjectCert->arena,
  386. &subjectSpki->algorithm.parameters,
  387. &issuerSpki->algorithm.parameters);
  388. }
  389. loser:
  390. if (issuerCert) {
  391. CERT_DestroyCertificate(issuerCert);
  392. }
  393. return rv;
  394. }
  395. SECStatus
  396. SECKEY_UpdateCertPQG(CERTCertificate * subjectCert)
  397. {
  398. if (!subjectCert) {
  399. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  400. return SECFailure;
  401. }
  402. return seckey_UpdateCertPQGChain(subjectCert,0);
  403. }
  404. /* Decode the DSA PQG parameters. The params could be stored in two
  405. * possible formats, the old fortezza-only wrapped format or
  406. * the normal standard format. Store the decoded parameters in
  407. * a V3 certificate data structure. */
  408. SECStatus
  409. SECKEY_DSADecodePQG(PRArenaPool *arena, SECKEYPublicKey *pubk, SECItem *params) {
  410. SECStatus rv;
  411. SECItem newparams;
  412. if (params == NULL) return SECFailure;
  413. if (params->data == NULL) return SECFailure;
  414. PORT_Assert(arena);
  415. /* make a copy of the data into the arena so QuickDER output is valid */
  416. rv = SECITEM_CopyItem(arena, &newparams, params);
  417. /* Check if params use the standard format.
  418. * The value 0xa1 will appear in the first byte of the parameter data
  419. * if the PQG parameters are not using the standard format. This
  420. * code should be changed to use a better method to detect non-standard
  421. * parameters. */
  422. if ((newparams.data[0] != 0xa1) &&
  423. (newparams.data[0] != 0xa0)) {
  424. if (SECSuccess == rv) {
  425. /* PQG params are in the standard format */
  426. prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
  427. rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params,
  428. SECKEY_PQGParamsTemplate,
  429. &newparams);
  430. }
  431. } else {
  432. if (SECSuccess == rv) {
  433. /* else the old fortezza-only wrapped format is used. */
  434. PORT_SetError(SEC_ERROR_BAD_DER);
  435. rv = SECFailure;
  436. }
  437. }
  438. return rv;
  439. }
  440. /* Function used to make an oid tag to a key type */
  441. KeyType
  442. seckey_GetKeyType (SECOidTag tag) {
  443. KeyType keyType;
  444. switch (tag) {
  445. case SEC_OID_X500_RSA_ENCRYPTION:
  446. case SEC_OID_PKCS1_RSA_ENCRYPTION:
  447. keyType = rsaKey;
  448. break;
  449. case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
  450. keyType = rsaPssKey;
  451. break;
  452. case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION:
  453. keyType = rsaOaepKey;
  454. break;
  455. case SEC_OID_ANSIX9_DSA_SIGNATURE:
  456. keyType = dsaKey;
  457. break;
  458. case SEC_OID_MISSI_KEA_DSS_OLD:
  459. case SEC_OID_MISSI_KEA_DSS:
  460. case SEC_OID_MISSI_DSS_OLD:
  461. case SEC_OID_MISSI_DSS:
  462. keyType = fortezzaKey;
  463. break;
  464. case SEC_OID_MISSI_KEA:
  465. case SEC_OID_MISSI_ALT_KEA:
  466. keyType = keaKey;
  467. break;
  468. case SEC_OID_X942_DIFFIE_HELMAN_KEY:
  469. keyType = dhKey;
  470. break;
  471. case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
  472. keyType = ecKey;
  473. break;
  474. /* accommodate applications that hand us a signature type when they
  475. * should be handing us a cipher type */
  476. case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
  477. case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
  478. case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
  479. case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
  480. case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
  481. case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
  482. keyType = rsaKey;
  483. break;
  484. default:
  485. keyType = nullKey;
  486. }
  487. return keyType;
  488. }
  489. /* Function used to determine what kind of cert we are dealing with. */
  490. KeyType
  491. CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki)
  492. {
  493. return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm));
  494. }
  495. static SECKEYPublicKey *
  496. seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
  497. {
  498. SECKEYPublicKey *pubk;
  499. SECItem os, newOs, newParms;
  500. SECStatus rv;
  501. PRArenaPool *arena;
  502. SECOidTag tag;
  503. arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  504. if (arena == NULL)
  505. return NULL;
  506. pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
  507. if (pubk == NULL) {
  508. PORT_FreeArena (arena, PR_FALSE);
  509. return NULL;
  510. }
  511. pubk->arena = arena;
  512. pubk->pkcs11Slot = 0;
  513. pubk->pkcs11ID = CK_INVALID_HANDLE;
  514. /* Convert bit string length from bits to bytes */
  515. os = spki->subjectPublicKey;
  516. DER_ConvertBitString (&os);
  517. tag = SECOID_GetAlgorithmTag(&spki->algorithm);
  518. /* copy the DER into the arena, since Quick DER returns data that points
  519. into the DER input, which may get freed by the caller */
  520. rv = SECITEM_CopyItem(arena, &newOs, &os);
  521. if ( rv == SECSuccess )
  522. switch ( tag ) {
  523. case SEC_OID_X500_RSA_ENCRYPTION:
  524. case SEC_OID_PKCS1_RSA_ENCRYPTION:
  525. pubk->keyType = rsaKey;
  526. prepare_rsa_pub_key_for_asn1(pubk);
  527. rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs);
  528. if (rv == SECSuccess)
  529. return pubk;
  530. break;
  531. case SEC_OID_ANSIX9_DSA_SIGNATURE:
  532. case SEC_OID_SDN702_DSA_SIGNATURE:
  533. pubk->keyType = dsaKey;
  534. prepare_dsa_pub_key_for_asn1(pubk);
  535. rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs);
  536. if (rv != SECSuccess) break;
  537. rv = SECKEY_DSADecodePQG(arena, pubk,
  538. &spki->algorithm.parameters);
  539. if (rv == SECSuccess) return pubk;
  540. break;
  541. case SEC_OID_X942_DIFFIE_HELMAN_KEY:
  542. pubk->keyType = dhKey;
  543. prepare_dh_pub_key_for_asn1(pubk);
  544. rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs);
  545. if (rv != SECSuccess) break;
  546. /* copy the DER into the arena, since Quick DER returns data that points
  547. into the DER input, which may get freed by the caller */
  548. rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
  549. if ( rv != SECSuccess )
  550. break;
  551. rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate,
  552. &newParms);
  553. if (rv == SECSuccess) return pubk;
  554. break;
  555. case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
  556. pubk->keyType = ecKey;
  557. pubk->u.ec.size = 0;
  558. /* Since PKCS#11 directly takes the DER encoding of EC params
  559. * and public value, we don't need any decoding here.
  560. */
  561. rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams,
  562. &spki->algorithm.parameters);
  563. if ( rv != SECSuccess )
  564. break;
  565. rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
  566. if (rv == SECSuccess) return pubk;
  567. break;
  568. default:
  569. PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
  570. rv = SECFailure;
  571. break;
  572. }
  573. SECKEY_DestroyPublicKey (pubk);
  574. return NULL;
  575. }
  576. /* required for JSS */
  577. SECKEYPublicKey *
  578. SECKEY_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
  579. {
  580. return seckey_ExtractPublicKey(spki);
  581. }
  582. SECKEYPublicKey *
  583. CERT_ExtractPublicKey(CERTCertificate *cert)
  584. {
  585. SECStatus rv;
  586. if (!cert) {
  587. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  588. return NULL;
  589. }
  590. rv = SECKEY_UpdateCertPQG(cert);
  591. if (rv != SECSuccess) return NULL;
  592. return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
  593. }
  594. int
  595. SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
  596. {
  597. SECOidTag tag;
  598. SECItem oid = { siBuffer, NULL, 0};
  599. /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
  600. * followed by the length of the curve oid and the curve oid.
  601. */
  602. oid.len = encodedParams->data[1];
  603. oid.data = encodedParams->data + 2;
  604. if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
  605. return 0;
  606. switch (tag) {
  607. case SEC_OID_SECG_EC_SECP112R1:
  608. case SEC_OID_SECG_EC_SECP112R2:
  609. return 112;
  610. case SEC_OID_SECG_EC_SECT113R1:
  611. case SEC_OID_SECG_EC_SECT113R2:
  612. return 113;
  613. case SEC_OID_SECG_EC_SECP128R1:
  614. case SEC_OID_SECG_EC_SECP128R2:
  615. return 128;
  616. case SEC_OID_SECG_EC_SECT131R1:
  617. case SEC_OID_SECG_EC_SECT131R2:
  618. return 131;
  619. case SEC_OID_SECG_EC_SECP160K1:
  620. case SEC_OID_SECG_EC_SECP160R1:
  621. case SEC_OID_SECG_EC_SECP160R2:
  622. return 160;
  623. case SEC_OID_SECG_EC_SECT163K1:
  624. case SEC_OID_SECG_EC_SECT163R1:
  625. case SEC_OID_SECG_EC_SECT163R2:
  626. case SEC_OID_ANSIX962_EC_C2PNB163V1:
  627. case SEC_OID_ANSIX962_EC_C2PNB163V2:
  628. case SEC_OID_ANSIX962_EC_C2PNB163V3:
  629. return 163;
  630. case SEC_OID_ANSIX962_EC_C2PNB176V1:
  631. return 176;
  632. case SEC_OID_ANSIX962_EC_C2TNB191V1:
  633. case SEC_OID_ANSIX962_EC_C2TNB191V2:
  634. case SEC_OID_ANSIX962_EC_C2TNB191V3:
  635. case SEC_OID_ANSIX962_EC_C2ONB191V4:
  636. case SEC_OID_ANSIX962_EC_C2ONB191V5:
  637. return 191;
  638. case SEC_OID_SECG_EC_SECP192K1:
  639. case SEC_OID_ANSIX962_EC_PRIME192V1:
  640. case SEC_OID_ANSIX962_EC_PRIME192V2:
  641. case SEC_OID_ANSIX962_EC_PRIME192V3:
  642. return 192;
  643. case SEC_OID_SECG_EC_SECT193R1:
  644. case SEC_OID_SECG_EC_SECT193R2:
  645. return 193;
  646. case SEC_OID_ANSIX962_EC_C2PNB208W1:
  647. return 208;
  648. case SEC_OID_SECG_EC_SECP224K1:
  649. case SEC_OID_SECG_EC_SECP224R1:
  650. return 224;
  651. case SEC_OID_SECG_EC_SECT233K1:
  652. case SEC_OID_SECG_EC_SECT233R1:
  653. return 233;
  654. case SEC_OID_SECG_EC_SECT239K1:
  655. case SEC_OID_ANSIX962_EC_C2TNB239V1:
  656. case SEC_OID_ANSIX962_EC_C2TNB239V2:
  657. case SEC_OID_ANSIX962_EC_C2TNB239V3:
  658. case SEC_OID_ANSIX962_EC_C2ONB239V4:
  659. case SEC_OID_ANSIX962_EC_C2ONB239V5:
  660. case SEC_OID_ANSIX962_EC_PRIME239V1:
  661. case SEC_OID_ANSIX962_EC_PRIME239V2:
  662. case SEC_OID_ANSIX962_EC_PRIME239V3:
  663. return 239;
  664. case SEC_OID_SECG_EC_SECP256K1:
  665. case SEC_OID_ANSIX962_EC_PRIME256V1:
  666. return 256;
  667. case SEC_OID_ANSIX962_EC_C2PNB272W1:
  668. return 272;
  669. case SEC_OID_SECG_EC_SECT283K1:
  670. case SEC_OID_SECG_EC_SECT283R1:
  671. return 283;
  672. case SEC_OID_ANSIX962_EC_C2PNB304W1:
  673. return 304;
  674. case SEC_OID_ANSIX962_EC_C2TNB359V1:
  675. return 359;
  676. case SEC_OID_ANSIX962_EC_C2PNB368W1:
  677. return 368;
  678. case SEC_OID_SECG_EC_SECP384R1:
  679. return 384;
  680. case SEC_OID_SECG_EC_SECT409K1:
  681. case SEC_OID_SECG_EC_SECT409R1:
  682. return 409;
  683. case SEC_OID_ANSIX962_EC_C2TNB431R1:
  684. return 431;
  685. case SEC_OID_SECG_EC_SECP521R1:
  686. return 521;
  687. case SEC_OID_SECG_EC_SECT571K1:
  688. case SEC_OID_SECG_EC_SECT571R1:
  689. return 571;
  690. default:
  691. PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
  692. return 0;
  693. }
  694. }
  695. int
  696. SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
  697. {
  698. SECOidTag tag;
  699. SECItem oid = { siBuffer, NULL, 0};
  700. /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
  701. * followed by the length of the curve oid and the curve oid.
  702. */
  703. oid.len = encodedParams->data[1];
  704. oid.data = encodedParams->data + 2;
  705. if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
  706. return 0;
  707. switch (tag) {
  708. case SEC_OID_SECG_EC_SECP112R1:
  709. return 112;
  710. case SEC_OID_SECG_EC_SECP112R2:
  711. return 110;
  712. case SEC_OID_SECG_EC_SECT113R1:
  713. case SEC_OID_SECG_EC_SECT113R2:
  714. return 113;
  715. case SEC_OID_SECG_EC_SECP128R1:
  716. return 128;
  717. case SEC_OID_SECG_EC_SECP128R2:
  718. return 126;
  719. case SEC_OID_SECG_EC_SECT131R1:
  720. case SEC_OID_SECG_EC_SECT131R2:
  721. return 131;
  722. case SEC_OID_SECG_EC_SECP160K1:
  723. case SEC_OID_SECG_EC_SECP160R1:
  724. case SEC_OID_SECG_EC_SECP160R2:
  725. return 161;
  726. case SEC_OID_SECG_EC_SECT163K1:
  727. return 163;
  728. case SEC_OID_SECG_EC_SECT163R1:
  729. return 162;
  730. case SEC_OID_SECG_EC_SECT163R2:
  731. case SEC_OID_ANSIX962_EC_C2PNB163V1:
  732. return 163;
  733. case SEC_OID_ANSIX962_EC_C2PNB163V2:
  734. case SEC_OID_ANSIX962_EC_C2PNB163V3:
  735. return 162;
  736. case SEC_OID_ANSIX962_EC_C2PNB176V1:
  737. return 161;
  738. case SEC_OID_ANSIX962_EC_C2TNB191V1:
  739. return 191;
  740. case SEC_OID_ANSIX962_EC_C2TNB191V2:
  741. return 190;
  742. case SEC_OID_ANSIX962_EC_C2TNB191V3:
  743. return 189;
  744. case SEC_OID_ANSIX962_EC_C2ONB191V4:
  745. return 191;
  746. case SEC_OID_ANSIX962_EC_C2ONB191V5:
  747. return 188;
  748. case SEC_OID_SECG_EC_SECP192K1:
  749. case SEC_OID_ANSIX962_EC_PRIME192V1:
  750. case SEC_OID_ANSIX962_EC_PRIME192V2:
  751. case SEC_OID_ANSIX962_EC_PRIME192V3:
  752. return 192;
  753. case SEC_OID_SECG_EC_SECT193R1:
  754. case SEC_OID_SECG_EC_SECT193R2:
  755. return 193;
  756. case SEC_OID_ANSIX962_EC_C2PNB208W1:
  757. return 193;
  758. case SEC_OID_SECG_EC_SECP224K1:
  759. return 225;
  760. case SEC_OID_SECG_EC_SECP224R1:
  761. return 224;
  762. case SEC_OID_SECG_EC_SECT233K1:
  763. return 232;
  764. case SEC_OID_SECG_EC_SECT233R1:
  765. return 233;
  766. case SEC_OID_SECG_EC_SECT239K1:
  767. case SEC_OID_ANSIX962_EC_C2TNB239V1:
  768. return 238;
  769. case SEC_OID_ANSIX962_EC_C2TNB239V2:
  770. return 237;
  771. case SEC_OID_ANSIX962_EC_C2TNB239V3:
  772. return 236;
  773. case SEC_OID_ANSIX962_EC_C2ONB239V4:
  774. return 238;
  775. case SEC_OID_ANSIX962_EC_C2ONB239V5:
  776. return 237;
  777. case SEC_OID_ANSIX962_EC_PRIME239V1:
  778. case SEC_OID_ANSIX962_EC_PRIME239V2:
  779. case SEC_OID_ANSIX962_EC_PRIME239V3:
  780. return 239;
  781. case SEC_OID_SECG_EC_SECP256K1:
  782. case SEC_OID_ANSIX962_EC_PRIME256V1:
  783. return 256;
  784. case SEC_OID_ANSIX962_EC_C2PNB272W1:
  785. return 257;
  786. case SEC_OID_SECG_EC_SECT283K1:
  787. return 281;
  788. case SEC_OID_SECG_EC_SECT283R1:
  789. return 282;
  790. case SEC_OID_ANSIX962_EC_C2PNB304W1:
  791. return 289;
  792. case SEC_OID_ANSIX962_EC_C2TNB359V1:
  793. return 353;
  794. case SEC_OID_ANSIX962_EC_C2PNB368W1:
  795. return 353;
  796. case SEC_OID_SECG_EC_SECP384R1:
  797. return 384;
  798. case SEC_OID_SECG_EC_SECT409K1:
  799. return 407;
  800. case SEC_OID_SECG_EC_SECT409R1:
  801. return 409;
  802. case SEC_OID_ANSIX962_EC_C2TNB431R1:
  803. return 418;
  804. case SEC_OID_SECG_EC_SECP521R1:
  805. return 521;
  806. case SEC_OID_SECG_EC_SECT571K1:
  807. case SEC_OID_SECG_EC_SECT571R1:
  808. return 570;
  809. default:
  810. PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
  811. return 0;
  812. }
  813. }
  814. /* returns key strength in bytes (not bits) */
  815. unsigned
  816. SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
  817. {
  818. unsigned char b0;
  819. unsigned size;
  820. /* interpret modulus length as key strength */
  821. if (!pubk)
  822. goto loser;
  823. switch (pubk->keyType) {
  824. case rsaKey:
  825. if (!pubk->u.rsa.modulus.data) break;
  826. b0 = pubk->u.rsa.modulus.data[0];
  827. return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
  828. case dsaKey:
  829. if (!pubk->u.dsa.publicValue.data) break;
  830. b0 = pubk->u.dsa.publicValue.data[0];
  831. return b0 ? pubk->u.dsa.publicValue.len :
  832. pubk->u.dsa.publicValue.len - 1;
  833. case dhKey:
  834. if (!pubk->u.dh.publicValue.data) break;
  835. b0 = pubk->u.dh.publicValue.data[0];
  836. return b0 ? pubk->u.dh.publicValue.len :
  837. pubk->u.dh.publicValue.len - 1;
  838. case ecKey:
  839. /* Get the key size in bits and adjust */
  840. size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
  841. return (size + 7)/8;
  842. default:
  843. break;
  844. }
  845. loser:
  846. PORT_SetError(SEC_ERROR_INVALID_KEY);
  847. return 0;
  848. }
  849. /* returns key strength in bits */
  850. unsigned
  851. SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
  852. {
  853. unsigned size;
  854. switch (pubk->keyType) {
  855. case rsaKey:
  856. case dsaKey:
  857. case dhKey:
  858. return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
  859. case ecKey:
  860. size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
  861. return size;
  862. default:
  863. break;
  864. }
  865. PORT_SetError(SEC_ERROR_INVALID_KEY);
  866. return 0;
  867. }
  868. /* returns signature length in bytes (not bits) */
  869. unsigned
  870. SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
  871. {
  872. unsigned char b0;
  873. unsigned size;
  874. switch (pubk->keyType) {
  875. case rsaKey:
  876. b0 = pubk->u.rsa.modulus.data[0];
  877. return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
  878. case dsaKey:
  879. return DSA_SIGNATURE_LEN;
  880. case ecKey:
  881. /* Get the base point order length in bits and adjust */
  882. size = SECKEY_ECParamsToBasePointOrderLen(
  883. &pubk->u.ec.DEREncodedParams);
  884. return ((size + 7)/8) * 2;
  885. default:
  886. break;
  887. }
  888. PORT_SetError(SEC_ERROR_INVALID_KEY);
  889. return 0;
  890. }
  891. SECKEYPrivateKey *
  892. SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk)
  893. {
  894. SECKEYPrivateKey *copyk;
  895. PRArenaPool *arena;
  896. if (!privk || !privk->pkcs11Slot) {
  897. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  898. return NULL;
  899. }
  900. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  901. if (arena == NULL) {
  902. return NULL;
  903. }
  904. copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey));
  905. if (copyk) {
  906. copyk->arena = arena;
  907. copyk->keyType = privk->keyType;
  908. /* copy the PKCS #11 parameters */
  909. copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
  910. /* if the key we're referencing was a temparary key we have just
  911. * created, that we want to go away when we're through, we need
  912. * to make a copy of it */
  913. if (privk->pkcs11IsTemp) {
  914. copyk->pkcs11ID =
  915. PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID);
  916. if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail;
  917. } else {
  918. copyk->pkcs11ID = privk->pkcs11ID;
  919. }
  920. copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
  921. copyk->wincx = privk->wincx;
  922. copyk->staticflags = privk->staticflags;
  923. return copyk;
  924. } else {
  925. PORT_SetError (SEC_ERROR_NO_MEMORY);
  926. }
  927. fail:
  928. PORT_FreeArena (arena, PR_FALSE);
  929. return NULL;
  930. }
  931. SECKEYPublicKey *
  932. SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
  933. {
  934. SECKEYPublicKey *copyk;
  935. PRArenaPool *arena;
  936. SECStatus rv = SECSuccess;
  937. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  938. if (arena == NULL) {
  939. PORT_SetError (SEC_ERROR_NO_MEMORY);
  940. return NULL;
  941. }
  942. copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
  943. if (!copyk) {
  944. PORT_FreeArena (arena, PR_FALSE);
  945. PORT_SetError (SEC_ERROR_NO_MEMORY);
  946. return NULL;
  947. }
  948. copyk->arena = arena;
  949. copyk->keyType = pubk->keyType;
  950. if (pubk->pkcs11Slot &&
  951. PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) {
  952. copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot);
  953. copyk->pkcs11ID = pubk->pkcs11ID;
  954. } else {
  955. copyk->pkcs11Slot = NULL; /* go get own reference */
  956. copyk->pkcs11ID = CK_INVALID_HANDLE;
  957. }
  958. switch (pubk->keyType) {
  959. case rsaKey:
  960. rv = SECITEM_CopyItem(arena, &copyk->u.rsa.modulus,
  961. &pubk->u.rsa.modulus);
  962. if (rv == SECSuccess) {
  963. rv = SECITEM_CopyItem (arena, &copyk->u.rsa.publicExponent,
  964. &pubk->u.rsa.publicExponent);
  965. if (rv == SECSuccess)
  966. return copyk;
  967. }
  968. break;
  969. case dsaKey:
  970. rv = SECITEM_CopyItem(arena, &copyk->u.dsa.publicValue,
  971. &pubk->u.dsa.publicValue);
  972. if (rv != SECSuccess) break;
  973. rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
  974. &pubk->u.dsa.params.prime);
  975. if (rv != SECSuccess) break;
  976. rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
  977. &pubk->u.dsa.params.subPrime);
  978. if (rv != SECSuccess) break;
  979. rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
  980. &pubk->u.dsa.params.base);
  981. break;
  982. case dhKey:
  983. rv = SECITEM_CopyItem(arena,&copyk->u.dh.prime,&pubk->u.dh.prime);
  984. if (rv != SECSuccess) break;
  985. rv = SECITEM_CopyItem(arena,&copyk->u.dh.base,&pubk->u.dh.base);
  986. if (rv != SECSuccess) break;
  987. rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue,
  988. &pubk->u.dh.publicValue);
  989. break;
  990. case ecKey:
  991. copyk->u.ec.size = pubk->u.ec.size;
  992. rv = SECITEM_CopyItem(arena,&copyk->u.ec.DEREncodedParams,
  993. &pubk->u.ec.DEREncodedParams);
  994. if (rv != SECSuccess) break;
  995. rv = SECITEM_CopyItem(arena,&copyk->u.ec.publicValue,
  996. &pubk->u.ec.publicValue);
  997. break;
  998. case nullKey:
  999. return copyk;
  1000. default:
  1001. PORT_SetError(SEC_ERROR_INVALID_KEY);
  1002. rv = SECFailure;
  1003. break;
  1004. }
  1005. if (rv == SECSuccess)
  1006. return copyk;
  1007. SECKEY_DestroyPublicKey (copyk);
  1008. return NULL;
  1009. }
  1010. SECKEYPublicKey *
  1011. SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
  1012. {
  1013. SECKEYPublicKey *pubk;
  1014. PRArenaPool *arena;
  1015. CERTCertificate *cert;
  1016. SECStatus rv;
  1017. /*
  1018. * First try to look up the cert.
  1019. */
  1020. cert = PK11_GetCertFromPrivateKey(privk);
  1021. if (cert) {
  1022. pubk = CERT_ExtractPublicKey(cert);
  1023. CERT_DestroyCertificate(cert);
  1024. return pubk;
  1025. }
  1026. /* couldn't find the cert, build pub key by hand */
  1027. arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  1028. if (arena == NULL) {
  1029. PORT_SetError (SEC_ERROR_NO_MEMORY);
  1030. return NULL;
  1031. }
  1032. pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
  1033. sizeof (SECKEYPublicKey));
  1034. if (pubk == NULL) {
  1035. PORT_FreeArena(arena,PR_FALSE);
  1036. return NULL;
  1037. }
  1038. pubk->keyType = privk->keyType;
  1039. pubk->pkcs11Slot = NULL;
  1040. pubk->pkcs11ID = CK_INVALID_HANDLE;
  1041. pubk->arena = arena;
  1042. switch(privk->keyType) {
  1043. case nullKey:
  1044. case dhKey:
  1045. case dsaKey:
  1046. /* Nothing to query, if the cert isn't there, we're done -- no way
  1047. * to get the public key */
  1048. break;
  1049. case rsaKey:
  1050. rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
  1051. CKA_MODULUS,arena,&pubk->u.rsa.modulus);
  1052. if (rv != SECSuccess) break;
  1053. rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
  1054. CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent);
  1055. if (rv != SECSuccess) break;
  1056. return pubk;
  1057. break;
  1058. default:
  1059. break;
  1060. }
  1061. PORT_FreeArena (arena, PR_FALSE);
  1062. return NULL;
  1063. }
  1064. CERTSubjectPublicKeyInfo *
  1065. SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
  1066. {
  1067. CERTSubjectPublicKeyInfo *spki;
  1068. PRArenaPool *arena;
  1069. SECItem params = { siBuffer, NULL, 0 };
  1070. if (!pubk) {
  1071. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1072. return NULL;
  1073. }
  1074. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1075. if (arena == NULL) {
  1076. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1077. return NULL;
  1078. }
  1079. spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki));
  1080. if (spki != NULL) {
  1081. SECStatus rv;
  1082. SECItem *rv_item;
  1083. spki->arena = arena;
  1084. switch(pubk->keyType) {
  1085. case rsaKey:
  1086. rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1087. SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
  1088. if (rv == SECSuccess) {
  1089. /*
  1090. * DER encode the public key into the subjectPublicKeyInfo.
  1091. */
  1092. prepare_rsa_pub_key_for_asn1(pubk);
  1093. rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
  1094. pubk, SECKEY_RSAPublicKeyTemplate);
  1095. if (rv_item != NULL) {
  1096. /*
  1097. * The stored value is supposed to be a BIT_STRING,
  1098. * so convert the length.
  1099. */
  1100. spki->subjectPublicKey.len <<= 3;
  1101. /*
  1102. * We got a good one; return it.
  1103. */
  1104. return spki;
  1105. }
  1106. }
  1107. break;
  1108. case dsaKey:
  1109. /* DER encode the params. */
  1110. prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
  1111. rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
  1112. SECKEY_PQGParamsTemplate);
  1113. if (rv_item != NULL) {
  1114. rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1115. SEC_OID_ANSIX9_DSA_SIGNATURE,
  1116. &params);
  1117. if (rv == SECSuccess) {
  1118. /*
  1119. * DER encode the public key into the subjectPublicKeyInfo.
  1120. */
  1121. prepare_dsa_pub_key_for_asn1(pubk);
  1122. rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
  1123. pubk,
  1124. SECKEY_DSAPublicKeyTemplate);
  1125. if (rv_item != NULL) {
  1126. /*
  1127. * The stored value is supposed to be a BIT_STRING,
  1128. * so convert the length.
  1129. */
  1130. spki->subjectPublicKey.len <<= 3;
  1131. /*
  1132. * We got a good one; return it.
  1133. */
  1134. return spki;
  1135. }
  1136. }
  1137. }
  1138. SECITEM_FreeItem(&params, PR_FALSE);
  1139. break;
  1140. case ecKey:
  1141. rv = SECITEM_CopyItem(arena, &params,
  1142. &pubk->u.ec.DEREncodedParams);
  1143. if (rv != SECSuccess) break;
  1144. rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1145. SEC_OID_ANSIX962_EC_PUBLIC_KEY,
  1146. &params);
  1147. if (rv != SECSuccess) break;
  1148. rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
  1149. &pubk->u.ec.publicValue);
  1150. if (rv == SECSuccess) {
  1151. /*
  1152. * The stored value is supposed to be a BIT_STRING,
  1153. * so convert the length.
  1154. */
  1155. spki->subjectPublicKey.len <<= 3;
  1156. /*
  1157. * We got a good one; return it.
  1158. */
  1159. return spki;
  1160. }
  1161. break;
  1162. case dhKey: /* later... */
  1163. break;
  1164. default:
  1165. break;
  1166. }
  1167. } else {
  1168. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1169. }
  1170. PORT_FreeArena(arena, PR_FALSE);
  1171. return NULL;
  1172. }
  1173. void
  1174. SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
  1175. {
  1176. if (spki && spki->arena) {
  1177. PORT_FreeArena(spki->arena, PR_FALSE);
  1178. }
  1179. }
  1180. /*
  1181. * this only works for RSA keys... need to do something
  1182. * similiar to CERT_ExtractPublicKey for other key times.
  1183. */
  1184. SECKEYPublicKey *
  1185. SECKEY_DecodeDERPublicKey(SECItem *pubkder)
  1186. {
  1187. PRArenaPool *arena;
  1188. SECKEYPublicKey *pubk;
  1189. SECStatus rv;
  1190. SECItem newPubkder;
  1191. arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  1192. if (arena == NULL) {
  1193. PORT_SetError (SEC_ERROR_NO_MEMORY);
  1194. return NULL;
  1195. }
  1196. pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
  1197. if (pubk != NULL) {
  1198. pubk->arena = arena;
  1199. pubk->pkcs11Slot = NULL;
  1200. pubk->pkcs11ID = 0;
  1201. prepare_rsa_pub_key_for_asn1(pubk);
  1202. /* copy the DER into the arena, since Quick DER returns data that points
  1203. into the DER input, which may get freed by the caller */
  1204. rv = SECITEM_CopyItem(arena, &newPubkder, pubkder);
  1205. if ( rv == SECSuccess ) {
  1206. rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate,
  1207. &newPubkder);
  1208. }
  1209. if (rv == SECSuccess)
  1210. return pubk;
  1211. SECKEY_DestroyPublicKey (pubk);
  1212. } else {
  1213. PORT_SetError (SEC_ERROR_NO_MEMORY);
  1214. }
  1215. PORT_FreeArena (arena, PR_FALSE);
  1216. return NULL;
  1217. }
  1218. /*
  1219. * Decode a base64 ascii encoded DER encoded public key.
  1220. */
  1221. SECKEYPublicKey *
  1222. SECKEY_ConvertAndDecodePublicKey(char *pubkstr)
  1223. {
  1224. SECKEYPublicKey *pubk;
  1225. SECStatus rv;
  1226. SECItem der;
  1227. rv = ATOB_ConvertAsciiToItem (&der, pubkstr);
  1228. if (rv != SECSuccess)
  1229. return NULL;
  1230. pubk = SECKEY_DecodeDERPublicKey (&der);
  1231. PORT_Free (der.data);
  1232. return pubk;
  1233. }
  1234. SECItem *
  1235. SECKEY_EncodeDERSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
  1236. {
  1237. CERTSubjectPublicKeyInfo *spki=NULL;
  1238. SECItem *spkiDER=NULL;
  1239. /* get the subjectpublickeyinfo */
  1240. spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
  1241. if( spki == NULL ) {
  1242. goto finish;
  1243. }
  1244. /* DER-encode the subjectpublickeyinfo */
  1245. spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki,
  1246. CERT_SubjectPublicKeyInfoTemplate);
  1247. SECKEY_DestroySubjectPublicKeyInfo(spki);
  1248. finish:
  1249. return spkiDER;
  1250. }
  1251. CERTSubjectPublicKeyInfo *
  1252. SECKEY_DecodeDERSubjectPublicKeyInfo(SECItem *spkider)
  1253. {
  1254. PRArenaPool *arena;
  1255. CERTSubjectPublicKeyInfo *spki;
  1256. SECStatus rv;
  1257. SECItem newSpkider;
  1258. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1259. if (arena == NULL) {
  1260. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1261. return NULL;
  1262. }
  1263. spki = (CERTSubjectPublicKeyInfo *)
  1264. PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo));
  1265. if (spki != NULL) {
  1266. spki->arena = arena;
  1267. /* copy the DER into the arena, since Quick DER returns data that points
  1268. into the DER input, which may get freed by the caller */
  1269. rv = SECITEM_CopyItem(arena, &newSpkider, spkider);
  1270. if ( rv == SECSuccess ) {
  1271. rv = SEC_QuickDERDecodeItem(arena,spki,
  1272. CERT_SubjectPublicKeyInfoTemplate, &newSpkider);
  1273. }
  1274. if (rv == SECSuccess)
  1275. return spki;
  1276. } else {
  1277. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1278. }
  1279. PORT_FreeArena(arena, PR_FALSE);
  1280. return NULL;
  1281. }
  1282. /*
  1283. * Decode a base64 ascii encoded DER encoded subject public key info.
  1284. */
  1285. CERTSubjectPublicKeyInfo *
  1286. SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(char *spkistr)
  1287. {
  1288. CERTSubjectPublicKeyInfo *spki;
  1289. SECStatus rv;
  1290. SECItem der;
  1291. rv = ATOB_ConvertAsciiToItem(&der, spkistr);
  1292. if (rv != SECSuccess)
  1293. return NULL;
  1294. spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
  1295. PORT_Free(der.data);
  1296. return spki;
  1297. }
  1298. /*
  1299. * Decode a base64 ascii encoded DER encoded public key and challenge
  1300. * Verify digital signature and make sure challenge matches
  1301. */
  1302. CERTSubjectPublicKeyInfo *
  1303. SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
  1304. void *wincx)
  1305. {
  1306. CERTSubjectPublicKeyInfo *spki = NULL;
  1307. CERTPublicKeyAndChallenge pkac;
  1308. SECStatus rv;
  1309. SECItem signedItem;
  1310. PRArenaPool *arena = NULL;
  1311. CERTSignedData sd;
  1312. SECItem sig;
  1313. SECKEYPublicKey *pubKey = NULL;
  1314. unsigned int len;
  1315. signedItem.data = NULL;
  1316. /* convert the base64 encoded data to binary */
  1317. rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
  1318. if (rv != SECSuccess) {
  1319. goto loser;
  1320. }
  1321. /* create an arena */
  1322. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1323. if (arena == NULL) {
  1324. goto loser;
  1325. }
  1326. /* decode the outer wrapping of signed data */
  1327. PORT_Memset(&sd, 0, sizeof(CERTSignedData));
  1328. rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem );
  1329. if ( rv ) {
  1330. goto loser;
  1331. }
  1332. /* decode the public key and challenge wrapper */
  1333. PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
  1334. rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate,
  1335. &sd.data);
  1336. if ( rv ) {
  1337. goto loser;
  1338. }
  1339. /* decode the subject public key info */
  1340. spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
  1341. if ( spki == NULL ) {
  1342. goto loser;
  1343. }
  1344. /* get the public key */
  1345. pubKey = seckey_ExtractPublicKey(spki);
  1346. if ( pubKey == NULL ) {
  1347. goto loser;
  1348. }
  1349. /* check the signature */
  1350. sig = sd.signature;
  1351. DER_ConvertBitString(&sig);
  1352. rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
  1353. &(sd.signatureAlgorithm), NULL, wincx);
  1354. if ( rv != SECSuccess ) {
  1355. goto loser;
  1356. }
  1357. /* check the challenge */
  1358. if ( challenge ) {
  1359. len = PORT_Strlen(challenge);
  1360. /* length is right */
  1361. if ( len != pkac.challenge.len ) {
  1362. goto loser;
  1363. }
  1364. /* actual data is right */
  1365. if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) {
  1366. goto loser;
  1367. }
  1368. }
  1369. goto done;
  1370. loser:
  1371. /* make sure that we return null if we got an error */
  1372. if ( spki ) {
  1373. SECKEY_DestroySubjectPublicKeyInfo(spki);
  1374. }
  1375. spki = NULL;
  1376. done:
  1377. if ( signedItem.data ) {
  1378. PORT_Free(signedItem.data);
  1379. }
  1380. if ( arena ) {
  1381. PORT_FreeArena(arena, PR_FALSE);
  1382. }
  1383. if ( pubKey ) {
  1384. SECKEY_DestroyPublicKey(pubKey);
  1385. }
  1386. return spki;
  1387. }
  1388. void
  1389. SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
  1390. PRBool freeit)
  1391. {
  1392. PRArenaPool *poolp;
  1393. if(pvk != NULL) {
  1394. if(pvk->arena) {
  1395. poolp = pvk->arena;
  1396. /* zero structure since PORT_FreeArena does not support
  1397. * this yet.
  1398. */
  1399. PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
  1400. PORT_Memset((char *)pvk, 0, sizeof(*pvk));
  1401. if(freeit == PR_TRUE) {
  1402. PORT_FreeArena(poolp, PR_TRUE);
  1403. } else {
  1404. pvk->arena = poolp;
  1405. }
  1406. } else {
  1407. SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
  1408. SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
  1409. SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
  1410. PORT_Memset((char *)pvk, 0, sizeof(*pvk));
  1411. if(freeit == PR_TRUE) {
  1412. PORT_Free(pvk);
  1413. }
  1414. }
  1415. }
  1416. }
  1417. void
  1418. SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
  1419. PRBool freeit)
  1420. {
  1421. PRArenaPool *poolp;
  1422. if(epki != NULL) {
  1423. if(epki->arena) {
  1424. poolp = epki->arena;
  1425. /* zero structure since PORT_FreeArena does not support
  1426. * this yet.
  1427. */
  1428. PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
  1429. PORT_Memset((char *)epki, 0, sizeof(*epki));
  1430. if(freeit == PR_TRUE) {
  1431. PORT_FreeArena(poolp, PR_TRUE);
  1432. } else {
  1433. epki->arena = poolp;
  1434. }
  1435. } else {
  1436. SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
  1437. SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
  1438. PORT_Memset((char *)epki, 0, sizeof(*epki));
  1439. if(freeit == PR_TRUE) {
  1440. PORT_Free(epki);
  1441. }
  1442. }
  1443. }
  1444. }
  1445. SECStatus
  1446. SECKEY_CopyPrivateKeyInfo(PRArenaPool *poolp,
  1447. SECKEYPrivateKeyInfo *to,
  1448. SECKEYPrivateKeyInfo *from)
  1449. {
  1450. SECStatus rv = SECFailure;
  1451. if((to == NULL) || (from == NULL)) {
  1452. return SECFailure;
  1453. }
  1454. rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
  1455. if(rv != SECSuccess) {
  1456. return SECFailure;
  1457. }
  1458. rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
  1459. if(rv != SECSuccess) {
  1460. return SECFailure;
  1461. }
  1462. rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
  1463. return rv;
  1464. }
  1465. SECStatus
  1466. SECKEY_CopyEncryptedPrivateKeyInfo(PRArenaPool *poolp,
  1467. SECKEYEncryptedPrivateKeyInfo *to,
  1468. SECKEYEncryptedPrivateKeyInfo *from)
  1469. {
  1470. SECStatus rv = SECFailure;
  1471. if((to == NULL) || (from == NULL)) {
  1472. return SECFailure;
  1473. }
  1474. rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
  1475. if(rv != SECSuccess) {
  1476. return SECFailure;
  1477. }
  1478. rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
  1479. return rv;
  1480. }
  1481. KeyType
  1482. SECKEY_GetPrivateKeyType(SECKEYPrivateKey *privKey)
  1483. {
  1484. return privKey->keyType;
  1485. }
  1486. KeyType
  1487. SECKEY_GetPublicKeyType(SECKEYPublicKey *pubKey)
  1488. {
  1489. return pubKey->keyType;
  1490. }
  1491. SECKEYPublicKey*
  1492. SECKEY_ImportDERPublicKey(SECItem *derKey, CK_KEY_TYPE type)
  1493. {
  1494. SECKEYPublicKey *pubk = NULL;
  1495. SECStatus rv = SECFailure;
  1496. SECItem newDerKey;
  1497. PRArenaPool *arena = NULL;
  1498. if (!derKey) {
  1499. return NULL;
  1500. }
  1501. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1502. if (arena == NULL) {
  1503. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1504. goto finish;
  1505. }
  1506. pubk = PORT_ArenaZNew(arena, SECKEYPublicKey);
  1507. if (pubk == NULL) {
  1508. goto finish;
  1509. }
  1510. pubk->arena = arena;
  1511. rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey);
  1512. if (SECSuccess != rv) {
  1513. goto finish;
  1514. }
  1515. pubk->pkcs11Slot = NULL;
  1516. pubk->pkcs11ID = CK_INVALID_HANDLE;
  1517. switch( type ) {
  1518. case CKK_RSA:
  1519. prepare_rsa_pub_key_for_asn1(pubk);
  1520. rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey);
  1521. pubk->keyType = rsaKey;
  1522. break;
  1523. case CKK_DSA:
  1524. prepare_dsa_pub_key_for_asn1(pubk);
  1525. rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey);
  1526. pubk->keyType = dsaKey;
  1527. break;
  1528. case CKK_DH:
  1529. prepare_dh_pub_key_for_asn1(pubk);
  1530. rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey);
  1531. pubk->keyType = dhKey;
  1532. break;
  1533. default:
  1534. rv = SECFailure;
  1535. break;
  1536. }
  1537. finish:
  1538. if (rv != SECSuccess) {
  1539. if (arena != NULL) {
  1540. PORT_FreeArena(arena, PR_TRUE);
  1541. }
  1542. pubk = NULL;
  1543. }
  1544. return pubk;
  1545. }
  1546. SECKEYPrivateKeyList*
  1547. SECKEY_NewPrivateKeyList(void)
  1548. {
  1549. PRArenaPool *arena = NULL;
  1550. SECKEYPrivateKeyList *ret = NULL;
  1551. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1552. if ( arena == NULL ) {
  1553. goto loser;
  1554. }
  1555. ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena,
  1556. sizeof(SECKEYPrivateKeyList));
  1557. if ( ret == NULL ) {
  1558. goto loser;
  1559. }
  1560. ret->arena = arena;
  1561. PR_INIT_CLIST(&ret->list);
  1562. return(ret);
  1563. loser:
  1564. if ( arena != NULL ) {
  1565. PORT_FreeArena(arena, PR_FALSE);
  1566. }
  1567. return(NULL);
  1568. }
  1569. void
  1570. SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys)
  1571. {
  1572. while( !PR_CLIST_IS_EMPTY(&keys->list) ) {
  1573. SECKEY_RemovePrivateKeyListNode(
  1574. (SECKEYPrivateKeyListNode*)(PR_LIST_HEAD(&keys->list)) );
  1575. }
  1576. PORT_FreeArena(keys->arena, PR_FALSE);
  1577. return;
  1578. }
  1579. void
  1580. SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node)
  1581. {
  1582. PR_ASSERT(node->key);
  1583. SECKEY_DestroyPrivateKey(node->key);
  1584. node->key = NULL;
  1585. PR_REMOVE_LINK(&node->links);
  1586. return;
  1587. }
  1588. SECStatus
  1589. SECKEY_AddPrivateKeyToListTail( SECKEYPrivateKeyList *list,
  1590. SECKEYPrivateKey *key)
  1591. {
  1592. SECKEYPrivateKeyListNode *node;
  1593. node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena,
  1594. sizeof(SECKEYPrivateKeyListNode));
  1595. if ( node == NULL ) {
  1596. goto loser;
  1597. }
  1598. PR_INSERT_BEFORE(&node->links, &list->list);
  1599. node->key = key;
  1600. return(SECSuccess);
  1601. loser:
  1602. return(SECFailure);
  1603. }
  1604. SECKEYPublicKeyList*
  1605. SECKEY_NewPublicKeyList(void)
  1606. {
  1607. PRArenaPool *arena = NULL;
  1608. SECKEYPublicKeyList *ret = NULL;
  1609. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1610. if ( arena == NULL ) {
  1611. goto loser;
  1612. }
  1613. ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena,
  1614. sizeof(SECKEYPublicKeyList));
  1615. if ( ret == NULL ) {
  1616. goto loser;
  1617. }
  1618. ret->arena = arena;
  1619. PR_INIT_CLIST(&ret->list);
  1620. return(ret);
  1621. loser:
  1622. if ( arena != NULL ) {
  1623. PORT_FreeArena(arena, PR_FALSE);
  1624. }
  1625. return(NULL);
  1626. }
  1627. void
  1628. SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys)
  1629. {
  1630. while( !PR_CLIST_IS_EMPTY(&keys->list) ) {
  1631. SECKEY_RemovePublicKeyListNode(
  1632. (SECKEYPublicKeyListNode*)(PR_LIST_HEAD(&keys->list)) );
  1633. }
  1634. PORT_FreeArena(keys->arena, PR_FALSE);
  1635. return;
  1636. }
  1637. void
  1638. SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node)
  1639. {
  1640. PR_ASSERT(node->key);
  1641. SECKEY_DestroyPublicKey(node->key);
  1642. node->key = NULL;
  1643. PR_REMOVE_LINK(&node->links);
  1644. return;
  1645. }
  1646. SECStatus
  1647. SECKEY_AddPublicKeyToListTail( SECKEYPublicKeyList *list,
  1648. SECKEYPublicKey *key)
  1649. {
  1650. SECKEYPublicKeyListNode *node;
  1651. node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena,
  1652. sizeof(SECKEYPublicKeyListNode));
  1653. if ( node == NULL ) {
  1654. goto loser;
  1655. }
  1656. PR_INSERT_BEFORE(&node->links, &list->list);
  1657. node->key = key;
  1658. return(SECSuccess);
  1659. loser:
  1660. return(SECFailure);
  1661. }
  1662. #define SECKEY_CacheAttribute(key, attribute) \
  1663. if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute)) { \
  1664. key->staticflags |= SECKEY_##attribute; \
  1665. } else { \
  1666. key->staticflags &= (~SECKEY_##attribute); \
  1667. }
  1668. SECStatus
  1669. SECKEY_CacheStaticFlags(SECKEYPrivateKey* key)
  1670. {
  1671. SECStatus rv = SECFailure;
  1672. if (key && key->pkcs11Slot && key->pkcs11ID) {
  1673. key->staticflags |= SECKEY_Attributes_Cached;
  1674. SECKEY_CacheAttribute(key, CKA_PRIVATE);
  1675. rv = SECSuccess;
  1676. }
  1677. return rv;
  1678. }