cmmfrec.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /* -*- Mode: C; tab-width: 8 -*-*/
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. * This file will implement the functions related to key recovery in
  7. * CMMF
  8. */
  9. #include "cmmf.h"
  10. #include "cmmfi.h"
  11. #include "secitem.h"
  12. #include "keyhi.h"
  13. CMMFKeyRecRepContent *
  14. CMMF_CreateKeyRecRepContent(void)
  15. {
  16. PLArenaPool *poolp;
  17. CMMFKeyRecRepContent *keyRecContent;
  18. poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
  19. if (poolp == NULL) {
  20. return NULL;
  21. }
  22. keyRecContent = PORT_ArenaZNew(poolp, CMMFKeyRecRepContent);
  23. if (keyRecContent == NULL) {
  24. PORT_FreeArena(poolp, PR_FALSE);
  25. return NULL;
  26. }
  27. keyRecContent->poolp = poolp;
  28. return keyRecContent;
  29. }
  30. SECStatus
  31. CMMF_DestroyKeyRecRepContent(CMMFKeyRecRepContent *inKeyRecRep)
  32. {
  33. PORT_Assert(inKeyRecRep != NULL);
  34. if (inKeyRecRep != NULL && inKeyRecRep->poolp != NULL) {
  35. int i;
  36. if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert != NULL) {
  37. CERT_DestroyCertificate(inKeyRecRep->newSigCert);
  38. }
  39. if (inKeyRecRep->caCerts != NULL) {
  40. for (i = 0; inKeyRecRep->caCerts[i] != NULL; i++) {
  41. CERT_DestroyCertificate(inKeyRecRep->caCerts[i]);
  42. }
  43. }
  44. if (inKeyRecRep->keyPairHist != NULL) {
  45. for (i = 0; inKeyRecRep->keyPairHist[i] != NULL; i++) {
  46. if (inKeyRecRep->keyPairHist[i]->certOrEncCert.choice ==
  47. cmmfCertificate) {
  48. CERT_DestroyCertificate(inKeyRecRep->keyPairHist[i]->certOrEncCert.cert.certificate);
  49. }
  50. }
  51. }
  52. PORT_FreeArena(inKeyRecRep->poolp, PR_TRUE);
  53. }
  54. return SECSuccess;
  55. }
  56. SECStatus
  57. CMMF_KeyRecRepContentSetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep,
  58. CMMFPKIStatus inPKIStatus)
  59. {
  60. PORT_Assert(inKeyRecRep != NULL && inPKIStatus >= cmmfGranted &&
  61. inPKIStatus < cmmfNumPKIStatus);
  62. if (inKeyRecRep == NULL) {
  63. return SECFailure;
  64. }
  65. return cmmf_PKIStatusInfoSetStatus(&inKeyRecRep->status,
  66. inKeyRecRep->poolp,
  67. inPKIStatus);
  68. }
  69. SECStatus
  70. CMMF_KeyRecRepContentSetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep,
  71. CERTCertificate *inNewSignCert)
  72. {
  73. PORT_Assert(inKeyRecRep != NULL && inNewSignCert != NULL);
  74. if (inKeyRecRep == NULL || inNewSignCert == NULL) {
  75. return SECFailure;
  76. }
  77. if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert) {
  78. CERT_DestroyCertificate(inKeyRecRep->newSigCert);
  79. }
  80. inKeyRecRep->isDecoded = PR_FALSE;
  81. inKeyRecRep->newSigCert = CERT_DupCertificate(inNewSignCert);
  82. return (inKeyRecRep->newSigCert == NULL) ? SECFailure : SECSuccess;
  83. }
  84. SECStatus
  85. CMMF_KeyRecRepContentSetCACerts(CMMFKeyRecRepContent *inKeyRecRep,
  86. CERTCertList *inCACerts)
  87. {
  88. SECStatus rv;
  89. void *mark;
  90. PORT_Assert(inKeyRecRep != NULL && inCACerts != NULL);
  91. if (inKeyRecRep == NULL || inCACerts == NULL) {
  92. return SECFailure;
  93. }
  94. mark = PORT_ArenaMark(inKeyRecRep->poolp);
  95. rv = cmmf_ExtractCertsFromList(inCACerts, inKeyRecRep->poolp,
  96. &inKeyRecRep->caCerts);
  97. if (rv != SECSuccess) {
  98. PORT_ArenaRelease(inKeyRecRep->poolp, mark);
  99. } else {
  100. PORT_ArenaUnmark(inKeyRecRep->poolp, mark);
  101. }
  102. return rv;
  103. }
  104. SECStatus
  105. CMMF_KeyRecRepContentSetCertifiedKeyPair(CMMFKeyRecRepContent *inKeyRecRep,
  106. CERTCertificate *inCert,
  107. SECKEYPrivateKey *inPrivKey,
  108. SECKEYPublicKey *inPubKey)
  109. {
  110. CMMFCertifiedKeyPair *keyPair;
  111. CRMFEncryptedValue *dummy;
  112. PLArenaPool *poolp;
  113. void *mark;
  114. SECStatus rv;
  115. PORT_Assert(inKeyRecRep != NULL &&
  116. inCert != NULL &&
  117. inPrivKey != NULL &&
  118. inPubKey != NULL);
  119. if (inKeyRecRep == NULL ||
  120. inCert == NULL ||
  121. inPrivKey == NULL ||
  122. inPubKey == NULL) {
  123. return SECFailure;
  124. }
  125. poolp = inKeyRecRep->poolp;
  126. mark = PORT_ArenaMark(poolp);
  127. if (inKeyRecRep->keyPairHist == NULL) {
  128. inKeyRecRep->keyPairHist = PORT_ArenaNewArray(poolp,
  129. CMMFCertifiedKeyPair *,
  130. (CMMF_MAX_KEY_PAIRS + 1));
  131. if (inKeyRecRep->keyPairHist == NULL) {
  132. goto loser;
  133. }
  134. inKeyRecRep->allocKeyPairs = CMMF_MAX_KEY_PAIRS;
  135. inKeyRecRep->numKeyPairs = 0;
  136. }
  137. if (inKeyRecRep->allocKeyPairs == inKeyRecRep->numKeyPairs) {
  138. goto loser;
  139. }
  140. keyPair = PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair);
  141. if (keyPair == NULL) {
  142. goto loser;
  143. }
  144. rv = cmmf_CertOrEncCertSetCertificate(&keyPair->certOrEncCert,
  145. poolp, inCert);
  146. if (rv != SECSuccess) {
  147. goto loser;
  148. }
  149. keyPair->privateKey = PORT_ArenaZNew(poolp, CRMFEncryptedValue);
  150. if (keyPair->privateKey == NULL) {
  151. goto loser;
  152. }
  153. dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey, inPubKey,
  154. keyPair->privateKey);
  155. PORT_Assert(dummy == keyPair->privateKey);
  156. if (dummy != keyPair->privateKey) {
  157. crmf_destroy_encrypted_value(dummy, PR_TRUE);
  158. goto loser;
  159. }
  160. inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = keyPair;
  161. inKeyRecRep->numKeyPairs++;
  162. inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = NULL;
  163. PORT_ArenaUnmark(poolp, mark);
  164. return SECSuccess;
  165. loser:
  166. PORT_ArenaRelease(poolp, mark);
  167. return SECFailure;
  168. }
  169. CMMFPKIStatus
  170. CMMF_KeyRecRepContentGetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep)
  171. {
  172. PORT_Assert(inKeyRecRep != NULL);
  173. if (inKeyRecRep == NULL) {
  174. return cmmfNoPKIStatus;
  175. }
  176. return cmmf_PKIStatusInfoGetStatus(&inKeyRecRep->status);
  177. }
  178. CERTCertificate *
  179. CMMF_KeyRecRepContentGetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep)
  180. {
  181. PORT_Assert(inKeyRecRep != NULL);
  182. if (inKeyRecRep == NULL ||
  183. inKeyRecRep->newSigCert == NULL) {
  184. return NULL;
  185. }
  186. /* newSigCert may not be a real certificate, it may be a hand decoded
  187. * cert structure. This code makes sure we hand off a real, fully formed
  188. * CERTCertificate to the caller. TODO: This should move into the decode
  189. * portion so that we never wind up with a half formed CERTCertificate
  190. * here. In this case the call would be to CERT_DupCertificate.
  191. */
  192. return CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
  193. &inKeyRecRep->newSigCert->signatureWrap.data,
  194. NULL, PR_FALSE, PR_TRUE);
  195. }
  196. CERTCertList *
  197. CMMF_KeyRecRepContentGetCACerts(CMMFKeyRecRepContent *inKeyRecRep)
  198. {
  199. PORT_Assert(inKeyRecRep != NULL);
  200. if (inKeyRecRep == NULL || inKeyRecRep->caCerts == NULL) {
  201. return NULL;
  202. }
  203. return cmmf_MakeCertList(inKeyRecRep->caCerts);
  204. }
  205. int
  206. CMMF_KeyRecRepContentGetNumKeyPairs(CMMFKeyRecRepContent *inKeyRecRep)
  207. {
  208. PORT_Assert(inKeyRecRep != NULL);
  209. return (inKeyRecRep == NULL) ? 0 : inKeyRecRep->numKeyPairs;
  210. }
  211. PRBool
  212. cmmf_KeyRecRepContentIsValidIndex(CMMFKeyRecRepContent *inKeyRecRep,
  213. int inIndex)
  214. {
  215. int numKeyPairs = CMMF_KeyRecRepContentGetNumKeyPairs(inKeyRecRep);
  216. return (PRBool)(inIndex >= 0 && inIndex < numKeyPairs);
  217. }
  218. CMMFCertifiedKeyPair *
  219. CMMF_KeyRecRepContentGetCertKeyAtIndex(CMMFKeyRecRepContent *inKeyRecRep,
  220. int inIndex)
  221. {
  222. CMMFCertifiedKeyPair *newKeyPair;
  223. SECStatus rv;
  224. PORT_Assert(inKeyRecRep != NULL &&
  225. cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex));
  226. if (inKeyRecRep == NULL ||
  227. !cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)) {
  228. return NULL;
  229. }
  230. newKeyPair = PORT_ZNew(CMMFCertifiedKeyPair);
  231. if (newKeyPair == NULL) {
  232. return NULL;
  233. }
  234. rv = cmmf_CopyCertifiedKeyPair(NULL, newKeyPair,
  235. inKeyRecRep->keyPairHist[inIndex]);
  236. if (rv != SECSuccess) {
  237. CMMF_DestroyCertifiedKeyPair(newKeyPair);
  238. newKeyPair = NULL;
  239. }
  240. return newKeyPair;
  241. }
  242. SECStatus
  243. CMMF_CertifiedKeyPairUnwrapPrivKey(CMMFCertifiedKeyPair *inKeyPair,
  244. SECKEYPrivateKey *inPrivKey,
  245. SECItem *inNickName,
  246. PK11SlotInfo *inSlot,
  247. CERTCertDBHandle *inCertdb,
  248. SECKEYPrivateKey **destPrivKey,
  249. void *wincx)
  250. {
  251. CERTCertificate *cert;
  252. SECItem keyUsageValue = { siBuffer, NULL, 0 };
  253. unsigned char keyUsage = 0x0;
  254. SECKEYPublicKey *pubKey;
  255. SECStatus rv;
  256. PORT_Assert(inKeyPair != NULL &&
  257. inPrivKey != NULL && inCertdb != NULL);
  258. if (inKeyPair == NULL ||
  259. inPrivKey == NULL ||
  260. inKeyPair->privateKey == NULL ||
  261. inCertdb == NULL) {
  262. return SECFailure;
  263. }
  264. cert = CMMF_CertifiedKeyPairGetCertificate(inKeyPair, inCertdb);
  265. CERT_FindKeyUsageExtension(cert, &keyUsageValue);
  266. if (keyUsageValue.data != NULL) {
  267. keyUsage = keyUsageValue.data[3];
  268. PORT_Free(keyUsageValue.data);
  269. }
  270. pubKey = CERT_ExtractPublicKey(cert);
  271. rv = crmf_encrypted_value_unwrap_priv_key(NULL, inKeyPair->privateKey,
  272. inPrivKey, pubKey,
  273. inNickName, inSlot, keyUsage,
  274. destPrivKey, wincx);
  275. SECKEY_DestroyPublicKey(pubKey);
  276. CERT_DestroyCertificate(cert);
  277. return rv;
  278. }
  279. PRBool
  280. CMMF_KeyRecRepContentHasCACerts(CMMFKeyRecRepContent *inKeyRecRep)
  281. {
  282. PORT_Assert(inKeyRecRep != NULL);
  283. if (inKeyRecRep == NULL) {
  284. return PR_FALSE;
  285. }
  286. return (PRBool)(inKeyRecRep->caCerts != NULL &&
  287. inKeyRecRep->caCerts[0] != NULL);
  288. }