crmfcont.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:31k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 8 -*-*/
  2. /*
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #include "crmf.h"
  35. #include "crmfi.h"
  36. #include "pk11func.h"
  37. #include "keyhi.h"
  38. #include "secoid.h"
  39. static SECStatus
  40. crmf_modify_control_array (CRMFCertRequest *inCertReq, int count)
  41. {
  42.     if (count > 0) {
  43.         void *dummy = PORT_Realloc(inCertReq->controls, 
  44.    sizeof(CRMFControl*)*(count+2));
  45. if (dummy == NULL) {
  46.     return SECFailure;
  47. }
  48. inCertReq->controls = dummy;
  49.     } else {
  50.         inCertReq->controls = PORT_ZNewArray(CRMFControl*, 2);
  51.     }
  52.     return (inCertReq->controls == NULL) ? SECFailure : SECSuccess ;
  53. }
  54. static SECStatus
  55. crmf_add_new_control(CRMFCertRequest *inCertReq,SECOidTag inTag,
  56.      CRMFControl **destControl)
  57. {
  58.     SECOidData  *oidData;
  59.     SECStatus    rv;
  60.     PRArenaPool *poolp;
  61.     int          numControls = 0;
  62.     CRMFControl *newControl;
  63.     CRMFControl **controls;
  64.     void        *mark;
  65.     poolp = inCertReq->poolp;
  66.     if (poolp == NULL) {
  67.         return SECFailure;
  68.     }
  69.     mark = PORT_ArenaMark(poolp);
  70.     if (inCertReq->controls != NULL) {
  71.         while (inCertReq->controls[numControls] != NULL)
  72.     numControls++;
  73.     }
  74.     rv = crmf_modify_control_array(inCertReq, numControls);
  75.     if (rv != SECSuccess) {
  76.         goto loser;
  77.     }
  78.     controls = inCertReq->controls;
  79.     oidData = SECOID_FindOIDByTag(inTag);
  80.     newControl = *destControl = PORT_ArenaZNew(poolp,CRMFControl);
  81.     if (newControl == NULL) {
  82.         goto loser;
  83.     }
  84.     rv = SECITEM_CopyItem(poolp, &newControl->derTag, &oidData->oid);
  85.     if (rv != SECSuccess) {
  86.         goto loser;
  87.     }
  88.     newControl->tag = inTag;
  89.     controls[numControls] = newControl;
  90.     controls[numControls+1] = NULL;
  91.     PORT_ArenaUnmark(poolp, mark);
  92.     return SECSuccess;
  93.  loser:
  94.     PORT_ArenaRelease(poolp, mark);
  95.     *destControl = NULL;
  96.     return SECFailure;
  97.   
  98. }
  99. SECStatus
  100. crmf_add_secitem_control(CRMFCertRequest *inCertReq, SECItem *value,
  101.  SECOidTag inTag)
  102. {
  103.     SECStatus    rv;
  104.     CRMFControl *newControl;
  105.     void        *mark;
  106.     rv = crmf_add_new_control(inCertReq, inTag, &newControl);
  107.     if (rv != SECSuccess) {
  108.         return rv;
  109.     }
  110.     mark = PORT_ArenaMark(inCertReq->poolp);
  111.     rv = SECITEM_CopyItem(inCertReq->poolp, &newControl->derValue, value);
  112.     if (rv != SECSuccess) {
  113.         PORT_ArenaRelease(inCertReq->poolp, mark);
  114. return rv;
  115.     }
  116.     PORT_ArenaUnmark(inCertReq->poolp, mark);
  117.     return SECSuccess;
  118. }
  119. SECStatus
  120. CRMF_CertRequestSetRegTokenControl(CRMFCertRequest *inCertReq, SECItem *value)
  121. {
  122.     return crmf_add_secitem_control(inCertReq, value, 
  123.     SEC_OID_PKIX_REGCTRL_REGTOKEN);
  124. }
  125. SECStatus
  126. CRMF_CertRequestSetAuthenticatorControl (CRMFCertRequest *inCertReq, 
  127.  SECItem         *value)
  128. {
  129.     return crmf_add_secitem_control(inCertReq, value, 
  130.     SEC_OID_PKIX_REGCTRL_AUTHENTICATOR);
  131. }
  132. SECStatus
  133. crmf_destroy_encrypted_value(CRMFEncryptedValue *inEncrValue, PRBool freeit)
  134. {
  135.     if (inEncrValue != NULL) {
  136.         if (inEncrValue->intendedAlg) {
  137.     SECOID_DestroyAlgorithmID(inEncrValue->intendedAlg, PR_TRUE);
  138. }
  139. if (inEncrValue->symmAlg) {
  140.     SECOID_DestroyAlgorithmID(inEncrValue->symmAlg, PR_TRUE);
  141. }
  142.         if (inEncrValue->encSymmKey.data) {
  143.     PORT_Free(inEncrValue->encSymmKey.data);
  144. }
  145. if (inEncrValue->keyAlg) {
  146.     SECOID_DestroyAlgorithmID(inEncrValue->keyAlg, PR_TRUE);
  147. }
  148. if (inEncrValue->valueHint.data) {
  149.     PORT_Free(inEncrValue->valueHint.data);
  150. }
  151.         if (inEncrValue->encValue.data) {
  152.     PORT_Free(inEncrValue->encValue.data);
  153. }
  154. if (freeit) {
  155.     PORT_Free(inEncrValue);
  156. }
  157.     }
  158.     return SECSuccess;
  159. }
  160. SECStatus
  161. CRMF_DestroyEncryptedValue(CRMFEncryptedValue *inEncrValue)
  162. {
  163.     return crmf_destroy_encrypted_value(inEncrValue, PR_TRUE);
  164. }
  165. SECStatus
  166. crmf_copy_encryptedvalue_secalg(PRArenaPool     *poolp,
  167. SECAlgorithmID  *srcAlgId,
  168. SECAlgorithmID **destAlgId)
  169. {
  170.     SECAlgorithmID *newAlgId;
  171.     *destAlgId = newAlgId = (poolp != NULL) ?
  172.                             PORT_ArenaZNew(poolp, SECAlgorithmID) :
  173.                             PORT_ZNew(SECAlgorithmID);
  174.     if (newAlgId == NULL) {
  175.         return SECFailure;
  176.     }
  177.     
  178.     return SECOID_CopyAlgorithmID(poolp, newAlgId, srcAlgId);
  179. }
  180. SECStatus
  181. crmf_copy_encryptedvalue(PRArenaPool        *poolp,
  182.  CRMFEncryptedValue *srcValue,
  183.  CRMFEncryptedValue *destValue)
  184. {
  185.     SECStatus           rv;
  186.     if (srcValue->intendedAlg != NULL) {
  187.         rv = crmf_copy_encryptedvalue_secalg(poolp,
  188.      srcValue->intendedAlg,
  189.      &destValue->intendedAlg);
  190. if (rv != SECSuccess) {
  191.     goto loser;
  192. }
  193.     }
  194.     if (srcValue->symmAlg != NULL) {
  195.         rv = crmf_copy_encryptedvalue_secalg(poolp, 
  196.      srcValue->symmAlg,
  197.      &destValue->symmAlg);
  198. if (rv != SECSuccess) {
  199.     goto loser;
  200. }
  201.     }
  202.     if (srcValue->encSymmKey.data != NULL) {
  203.         rv = crmf_make_bitstring_copy(poolp, 
  204.       &destValue->encSymmKey,
  205.       &srcValue->encSymmKey);
  206. if (rv != SECSuccess) {
  207.     goto loser;
  208. }
  209.     }
  210.     if (srcValue->keyAlg != NULL) {
  211.         rv = crmf_copy_encryptedvalue_secalg(poolp,
  212.      srcValue->keyAlg,
  213.      &destValue->keyAlg);
  214. if (rv != SECSuccess) {
  215.     goto loser;
  216. }
  217.     }
  218.     if (srcValue->valueHint.data != NULL) {
  219.         rv = SECITEM_CopyItem(poolp, 
  220.       &destValue->valueHint,
  221.       &srcValue->valueHint);
  222. if (rv != SECSuccess) {
  223.     goto loser;
  224. }
  225.     }
  226.     if (srcValue->encValue.data != NULL) {
  227.         rv = crmf_make_bitstring_copy(poolp,
  228.       &destValue->encValue,
  229.       &srcValue->encValue);
  230. if (rv != SECSuccess) {
  231.     goto loser;
  232. }
  233.     }
  234.     return SECSuccess;
  235.  loser:
  236.     if (poolp == NULL && destValue != NULL) {
  237.         crmf_destroy_encrypted_value(destValue, PR_TRUE);
  238.     }
  239.     return SECFailure;
  240. }
  241. SECStatus 
  242. crmf_copy_encryptedkey(PRArenaPool       *poolp,
  243.        CRMFEncryptedKey  *srcEncrKey,
  244.        CRMFEncryptedKey  *destEncrKey)
  245. {
  246.     SECStatus          rv;
  247.     void              *mark;
  248.     if (poolp != NULL) {
  249.         mark = PORT_ArenaMark(poolp);
  250.     }
  251.     switch (srcEncrKey->encKeyChoice) {
  252.     case crmfEncryptedValueChoice:
  253.         rv = crmf_copy_encryptedvalue(poolp, 
  254.       &srcEncrKey->value.encryptedValue,
  255.       &destEncrKey->value.encryptedValue);
  256. break;
  257.     case crmfEnvelopedDataChoice:
  258.         destEncrKey->value.envelopedData = 
  259.     SEC_PKCS7CopyContentInfo(srcEncrKey->value.envelopedData);
  260.         rv = (destEncrKey->value.envelopedData != NULL) ? SECSuccess:
  261.                                                   SECFailure;
  262.         break;
  263.     default:
  264.         rv = SECFailure;
  265.     }
  266.     if (rv != SECSuccess) {
  267.         goto loser;
  268.     }
  269.     destEncrKey->encKeyChoice = srcEncrKey->encKeyChoice;
  270.     if (poolp != NULL) {
  271.      PORT_ArenaUnmark(poolp, mark);
  272.     }
  273.     return SECSuccess;
  274.  loser:
  275.     if (poolp != NULL) {
  276.         PORT_ArenaRelease(poolp, mark);
  277.     }
  278.     return SECFailure;
  279. }
  280. CRMFPKIArchiveOptions*
  281. crmf_create_encr_pivkey_option(CRMFEncryptedKey *inEncryptedKey)
  282. {
  283.     CRMFPKIArchiveOptions *newArchOpt;
  284.     SECStatus              rv;
  285.     newArchOpt = PORT_ZNew(CRMFPKIArchiveOptions);
  286.     if (newArchOpt == NULL) {
  287.         goto loser;
  288.     }
  289.     rv = crmf_copy_encryptedkey(NULL, inEncryptedKey,
  290. &newArchOpt->option.encryptedKey);
  291.     
  292.     if (rv != SECSuccess) {
  293.       goto loser;
  294.     }
  295.     newArchOpt->archOption = crmfEncryptedPrivateKey;
  296.     return newArchOpt;
  297.  loser:
  298.     if (newArchOpt != NULL) {
  299.         CRMF_DestroyPKIArchiveOptions(newArchOpt);
  300.     }
  301.     return NULL;
  302. }
  303. static CRMFPKIArchiveOptions*
  304. crmf_create_keygen_param_option(SECItem *inKeyGenParams)
  305. {
  306.     CRMFPKIArchiveOptions *newArchOptions;
  307.     SECStatus              rv;
  308.     newArchOptions = PORT_ZNew(CRMFPKIArchiveOptions);
  309.     if (newArchOptions == NULL) {
  310.         goto loser;
  311.     }
  312.     newArchOptions->archOption = crmfKeyGenParameters;
  313.     rv = SECITEM_CopyItem(NULL, &newArchOptions->option.keyGenParameters,
  314.   inKeyGenParams);
  315.     if (rv != SECSuccess) {
  316.         goto loser;
  317.     }
  318.     return newArchOptions;
  319.  loser:
  320.     if (newArchOptions != NULL) {
  321.         CRMF_DestroyPKIArchiveOptions(newArchOptions);
  322.     }
  323.     return NULL;
  324. }
  325. static CRMFPKIArchiveOptions*
  326. crmf_create_arch_rem_gen_privkey(PRBool archiveRemGenPrivKey)
  327. {
  328.     unsigned char          value;
  329.     SECItem               *dummy;
  330.     CRMFPKIArchiveOptions *newArchOptions;
  331.     value = (archiveRemGenPrivKey) ? hexTrue : hexFalse;
  332.     newArchOptions = PORT_ZNew(CRMFPKIArchiveOptions);
  333.     if (newArchOptions == NULL) {
  334.         goto loser;
  335.     }
  336.     dummy = SEC_ASN1EncodeItem(NULL, 
  337.        &newArchOptions->option.archiveRemGenPrivKey,
  338.        &value, SEC_BooleanTemplate);
  339.     PORT_Assert (dummy == &newArchOptions->option.archiveRemGenPrivKey);
  340.     if (dummy != &newArchOptions->option.archiveRemGenPrivKey) {
  341.         SECITEM_FreeItem (dummy, PR_TRUE);
  342. goto loser;
  343.     }
  344.     newArchOptions->archOption = crmfArchiveRemGenPrivKey;
  345.     return newArchOptions;
  346.  loser:
  347.     if (newArchOptions != NULL) {
  348.         CRMF_DestroyPKIArchiveOptions(newArchOptions);
  349.     }
  350.     return NULL;
  351. }
  352. CRMFPKIArchiveOptions*
  353. CRMF_CreatePKIArchiveOptions(CRMFPKIArchiveOptionsType inType, void *data)
  354. {
  355.     CRMFPKIArchiveOptions* retOptions;
  356.     PORT_Assert(data != NULL);
  357.     if (data == NULL) {
  358.         return NULL;
  359.     }
  360.     switch(inType) {
  361.     case crmfEncryptedPrivateKey:
  362.         retOptions = crmf_create_encr_pivkey_option((CRMFEncryptedKey*)data);
  363. break;
  364.     case crmfKeyGenParameters:
  365.         retOptions = crmf_create_keygen_param_option((SECItem*)data);
  366. break;
  367.     case crmfArchiveRemGenPrivKey:
  368.         retOptions = crmf_create_arch_rem_gen_privkey(*(PRBool*)data);
  369. break;
  370.     default:
  371.         retOptions = NULL;
  372.     }
  373.     return retOptions;
  374. }
  375. static SECStatus
  376. crmf_destroy_encrypted_key(CRMFEncryptedKey *inEncrKey, PRBool freeit)
  377.     PORT_Assert(inEncrKey != NULL);
  378.     if (inEncrKey != NULL) {
  379.         switch (inEncrKey->encKeyChoice){
  380. case crmfEncryptedValueChoice:
  381.             crmf_destroy_encrypted_value(&inEncrKey->value.encryptedValue, 
  382.  PR_FALSE);
  383.     break;
  384. case crmfEnvelopedDataChoice:
  385.     SEC_PKCS7DestroyContentInfo(inEncrKey->value.envelopedData);
  386.             break;
  387.         default:
  388.             break;
  389.         }
  390.         if (freeit) {
  391.             PORT_Free(inEncrKey);
  392.         }
  393.     }
  394.     return SECSuccess;
  395. }
  396. SECStatus 
  397. crmf_destroy_pkiarchiveoptions(CRMFPKIArchiveOptions *inArchOptions, 
  398.        PRBool                 freeit)
  399. {
  400.     PORT_Assert(inArchOptions != NULL);
  401.     if (inArchOptions != NULL) {
  402.         switch (inArchOptions->archOption) {
  403. case crmfEncryptedPrivateKey:
  404.     crmf_destroy_encrypted_key(&inArchOptions->option.encryptedKey,
  405.        PR_FALSE);
  406.     break;
  407. case crmfKeyGenParameters:
  408. case crmfArchiveRemGenPrivKey:
  409.     /* This is a union, so having a pointer to one is like
  410.      * having a pointer to both.  
  411.      */
  412.     SECITEM_FreeItem(&inArchOptions->option.keyGenParameters, 
  413.      PR_FALSE);
  414.     break;
  415.         case crmfNoArchiveOptions:
  416.             break;
  417. }
  418. if (freeit) {
  419.     PORT_Free(inArchOptions);
  420. }
  421.     }
  422.     return SECSuccess;
  423. }
  424. SECStatus
  425. CRMF_DestroyPKIArchiveOptions(CRMFPKIArchiveOptions *inArchOptions) 
  426. {
  427.     return crmf_destroy_pkiarchiveoptions(inArchOptions, PR_TRUE);
  428. }
  429. static CK_MECHANISM_TYPE
  430. crmf_get_non_pad_mechanism(CK_MECHANISM_TYPE type)
  431. {
  432.     switch (type) {
  433.     case CKM_DES3_CBC_PAD:
  434.         return CKM_DES3_CBC;
  435.     case CKM_CAST5_CBC_PAD:
  436.         return CKM_CAST5_CBC;
  437.     case CKM_DES_CBC_PAD:
  438.         return CKM_DES_CBC;
  439.     case CKM_IDEA_CBC_PAD:
  440.         return CKM_IDEA_CBC;
  441.     case CKM_CAST3_CBC_PAD:
  442.         return CKM_CAST3_CBC;
  443.     case CKM_CAST_CBC_PAD:
  444.         return CKM_CAST_CBC;
  445.     case CKM_RC5_CBC_PAD:
  446.         return CKM_RC5_CBC;
  447.     case CKM_RC2_CBC_PAD:
  448.         return CKM_RC2_CBC;
  449.     case CKM_CDMF_CBC_PAD:
  450.         return CKM_CDMF_CBC;
  451.     }
  452.     return type;
  453. }
  454. static CK_MECHANISM_TYPE
  455. crmf_get_pad_mech_from_tag(SECOidTag oidTag)
  456. {
  457.     CK_MECHANISM_TYPE  mechType;
  458.     SECOidData        *oidData;
  459.     oidData = SECOID_FindOIDByTag(oidTag);
  460.     mechType = (CK_MECHANISM_TYPE)oidData->mechanism;
  461.     return PK11_GetPadMechanism(mechType);
  462. }
  463. static CK_MECHANISM_TYPE
  464. crmf_get_best_privkey_wrap_mechanism(PK11SlotInfo *slot) 
  465. {
  466.     CK_MECHANISM_TYPE privKeyPadMechs[] = { CKM_DES3_CBC_PAD,
  467.     CKM_CAST5_CBC_PAD,
  468.     CKM_DES_CBC_PAD,
  469.     CKM_IDEA_CBC_PAD,
  470.     CKM_CAST3_CBC_PAD,
  471.     CKM_CAST_CBC_PAD,
  472.     CKM_RC5_CBC_PAD,
  473.     CKM_RC2_CBC_PAD,
  474.     CKM_CDMF_CBC_PAD };
  475.     int mechCount = sizeof(privKeyPadMechs)/sizeof(privKeyPadMechs[0]);
  476.     int i;
  477.     for (i=0; i < mechCount; i++) {
  478.         if (PK11_DoesMechanism(slot, privKeyPadMechs[i])) {
  479.     return privKeyPadMechs[i];
  480. }
  481.     }
  482.     return CKM_INVALID_MECHANISM;
  483. }
  484. CK_MECHANISM_TYPE
  485. CRMF_GetBestWrapPadMechanism(PK11SlotInfo *slot)
  486. {
  487.     return crmf_get_best_privkey_wrap_mechanism(slot);
  488. }
  489. static SECItem*
  490. crmf_get_iv(CK_MECHANISM_TYPE mechType)
  491. {
  492.     int        iv_size = PK11_GetIVLength(mechType);
  493.     SECItem   *iv;
  494.     SECStatus  rv; 
  495.     iv = PORT_ZNew(SECItem);
  496.     if (iv == NULL) {
  497.         return NULL;
  498.     }
  499.     if (iv_size == 0) {
  500.         iv->data = NULL;
  501. iv->len  = 0;
  502. return iv;
  503.     }
  504.     iv->data = PORT_NewArray(unsigned char, iv_size);
  505.     if (iv->data == NULL) {
  506.         iv->len = 0;
  507. return iv;
  508.     }
  509.     iv->len = iv_size;
  510.     rv = PK11_GenerateRandom(iv->data, iv->len);
  511.     if (rv != SECSuccess) {
  512.         PORT_Free(iv->data);
  513. iv->data = NULL;
  514. iv->len  = 0;
  515.     }
  516.     return iv;
  517. }
  518. SECItem*
  519. CRMF_GetIVFromMechanism(CK_MECHANISM_TYPE mechType)
  520. {
  521.     return crmf_get_iv(mechType);
  522. }
  523. CK_MECHANISM_TYPE
  524. crmf_get_mechanism_from_public_key(SECKEYPublicKey *inPubKey)
  525. {
  526.     CERTSubjectPublicKeyInfo *spki = NULL;
  527.     SECOidTag                 tag;
  528.     
  529.     spki = SECKEY_CreateSubjectPublicKeyInfo(inPubKey);
  530.     if (spki == NULL) {
  531.         return CKM_INVALID_MECHANISM;
  532.     }
  533.     tag = SECOID_FindOIDTag(&spki->algorithm.algorithm);
  534.     SECKEY_DestroySubjectPublicKeyInfo(spki);
  535.     spki = NULL;
  536.     return PK11_AlgtagToMechanism(tag);
  537. }
  538. SECItem*
  539. crmf_get_public_value(SECKEYPublicKey *pubKey, SECItem *dest)
  540. {
  541.     SECItem *pubValue;
  542.     if (dest != NULL) {
  543.         pubValue = dest;
  544.     } else {
  545.         pubValue = PORT_ZNew(SECItem);
  546.     }
  547.     switch(pubKey->keyType) {
  548.         case dsaKey:
  549.     SECITEM_CopyItem(NULL, pubValue, &pubKey->u.dsa.publicValue);
  550.             break;
  551.         case rsaKey:
  552.     SECITEM_CopyItem(NULL, pubValue, &pubKey->u.rsa.modulus);
  553.             break;
  554.         case dhKey:
  555.     SECITEM_CopyItem(NULL, pubValue, &pubKey->u.dh.publicValue);
  556.     break;
  557.         default:
  558.     if (dest == NULL) {
  559.         PORT_Free(pubValue);
  560.     }
  561.             pubValue = NULL;
  562.     break;
  563.     }
  564.     return pubValue;
  565. }
  566. static SECItem*
  567. crmf_decode_params(SECItem *inParams)
  568. {
  569.     SECItem   *params;
  570.     SECStatus  rv;
  571.     
  572.     params = PORT_ZNew(SECItem);
  573.     rv = SEC_ASN1DecodeItem(NULL, params, SEC_OctetStringTemplate,
  574.     inParams);
  575.     if (rv != SECSuccess) {
  576.         SECITEM_FreeItem(params, PR_TRUE);
  577. return NULL;
  578.     }
  579.     return params;
  580. }
  581. int
  582. crmf_get_key_size_from_mech(CK_MECHANISM_TYPE mechType)
  583. {
  584.     CK_MECHANISM_TYPE keyGen = PK11_GetKeyGen(mechType);
  585.     switch (keyGen) {
  586.     case CKM_CDMF_KEY_GEN:
  587.     case CKM_DES_KEY_GEN:
  588.         return 8;
  589.     case CKM_DES2_KEY_GEN:
  590. return 16;
  591.     case CKM_DES3_KEY_GEN:
  592. return 24;
  593.     }
  594.     return 0;
  595. }
  596. SECStatus
  597. crmf_encrypted_value_unwrap_priv_key(PRArenaPool        *poolp,
  598.      CRMFEncryptedValue *encValue,
  599.      SECKEYPrivateKey   *privKey,
  600.      SECKEYPublicKey    *newPubKey,
  601.      SECItem            *nickname,
  602.      PK11SlotInfo       *slot,
  603.      unsigned char       keyUsage,
  604.      SECKEYPrivateKey  **unWrappedKey,
  605.      void               *wincx)
  606. {
  607.     PK11SymKey        *wrappingKey = NULL;
  608.     CK_MECHANISM_TYPE  wrapMechType;
  609.     SECOidTag          oidTag;
  610.     SECItem           *params = NULL, *publicValue = NULL;
  611.     int                keySize, origLen;
  612.     CK_KEY_TYPE        keyType;
  613.     CK_ATTRIBUTE_TYPE *usage;
  614.     CK_ATTRIBUTE_TYPE rsaUsage[] = {
  615.       CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER };
  616.     CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN };
  617.     CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE };
  618.     int usageCount;
  619.     oidTag = SECOID_GetAlgorithmTag(encValue->symmAlg);
  620.     wrapMechType = crmf_get_pad_mech_from_tag(oidTag);
  621.     keySize = crmf_get_key_size_from_mech(wrapMechType);
  622.     wrappingKey = PK11_PubUnwrapSymKey(privKey, &encValue->encSymmKey, 
  623.        wrapMechType, CKA_UNWRAP, keySize);
  624.     if (wrappingKey == NULL) {
  625.         goto loser;
  626.     }/* Make the length a byte length instead of bit length*/
  627.     params = (encValue->symmAlg != NULL) ? 
  628.               crmf_decode_params(&encValue->symmAlg->parameters) : NULL;
  629.     origLen = encValue->encValue.len;
  630.     encValue->encValue.len = CRMF_BITS_TO_BYTES(origLen);
  631.     publicValue = crmf_get_public_value(newPubKey, NULL);
  632.     switch(newPubKey->keyType) {
  633.     default:
  634.     case rsaKey:
  635.         keyType = CKK_RSA;
  636.         switch  (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) {
  637.         case KU_KEY_ENCIPHERMENT:
  638.             usage = rsaUsage;
  639.             usageCount = 2;
  640.             break;
  641.         case KU_DIGITAL_SIGNATURE:
  642.             usage = &rsaUsage[2];
  643.             usageCount = 2;
  644.             break;
  645.         case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE:
  646.         case 0: /* default to everything */
  647.             usage = rsaUsage;
  648.             usageCount = 4;
  649.             break;
  650.         }
  651. break;
  652.     case dhKey:
  653.         keyType = CKK_DH;
  654.         usage = dhUsage;
  655.         usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]);
  656.         break;
  657.     case dsaKey:
  658.         keyType = CKK_DSA;
  659.         usage = dsaUsage;
  660.         usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]);
  661.         break;
  662.     }
  663.     *unWrappedKey = PK11_UnwrapPrivKey(slot, wrappingKey, wrapMechType, params,
  664.        &encValue->encValue, nickname,
  665.        publicValue, PR_TRUE,PR_TRUE, 
  666.        keyType, usage, usageCount, wincx);
  667.     encValue->encValue.len = origLen;
  668.     if (*unWrappedKey == NULL) {
  669.         goto loser;
  670.     }
  671.     SECITEM_FreeItem (publicValue, PR_TRUE);
  672.     if (params!= NULL) {
  673.         SECITEM_FreeItem(params, PR_TRUE);
  674.     } 
  675.     PK11_FreeSymKey(wrappingKey);
  676.     return SECSuccess;
  677.  loser:
  678.     *unWrappedKey = NULL;
  679.     return SECFailure;
  680. }
  681. CRMFEncryptedValue *
  682. crmf_create_encrypted_value_wrapped_privkey(SECKEYPrivateKey   *inPrivKey,
  683.     SECKEYPublicKey    *inCAKey,
  684.     CRMFEncryptedValue *destValue)
  685. {
  686.     SECItem                   wrappedPrivKey, wrappedSymKey;
  687.     SECItem                   encodedParam, *dummy;
  688.     SECStatus                 rv;
  689.     CK_MECHANISM_TYPE         pubMechType, symKeyType;
  690.     unsigned char            *wrappedSymKeyBits;
  691.     unsigned char            *wrappedPrivKeyBits;
  692.     SECItem                  *iv = NULL;
  693.     SECOidTag                 tag;
  694.     PK11SymKey               *symKey;
  695.     PK11SlotInfo             *slot;
  696.     SECAlgorithmID           *symmAlg;
  697.     CRMFEncryptedValue       *myEncrValue = NULL;
  698.     encodedParam.data = NULL;
  699.     wrappedSymKeyBits  = PORT_NewArray(unsigned char, MAX_WRAPPED_KEY_LEN);
  700.     wrappedPrivKeyBits = PORT_NewArray(unsigned char, MAX_WRAPPED_KEY_LEN);
  701.     if (wrappedSymKeyBits == NULL || wrappedPrivKeyBits == NULL) {
  702.         goto loser;
  703.     }
  704.     if (destValue == NULL) {
  705.         myEncrValue = destValue = PORT_ZNew(CRMFEncryptedValue);
  706. if (destValue == NULL) {
  707.     goto loser;
  708. }
  709.     }
  710.     pubMechType = crmf_get_mechanism_from_public_key(inCAKey);
  711.     if (pubMechType == CKM_INVALID_MECHANISM) {
  712.         /* XXX I should probably do something here for non-RSA 
  713.  *     keys that are in certs. (ie DSA)
  714.  */
  715.         goto loser;
  716.     }
  717.     slot = inPrivKey->pkcs11Slot; 
  718.     PORT_Assert(slot != NULL);
  719.     symKeyType = crmf_get_best_privkey_wrap_mechanism(slot);
  720.     symKey = PK11_KeyGen(slot, symKeyType, NULL, 0, NULL);
  721.     if (symKey == NULL) {
  722.         goto loser;
  723.     }
  724.     wrappedSymKey.data = wrappedSymKeyBits;
  725.     wrappedSymKey.len  = MAX_WRAPPED_KEY_LEN;
  726.     rv = PK11_PubWrapSymKey(pubMechType, inCAKey, symKey, &wrappedSymKey);
  727.     if (rv != SECSuccess) {
  728.         goto loser;
  729.     }
  730.     /* Make the length of the result a Bit String length. */
  731.     wrappedSymKey.len <<= 3;
  732.     wrappedPrivKey.data = wrappedPrivKeyBits;
  733.     wrappedPrivKey.len  = MAX_WRAPPED_KEY_LEN;
  734.     iv = crmf_get_iv(symKeyType);
  735.     rv = PK11_WrapPrivKey(slot, symKey, inPrivKey, symKeyType, iv, 
  736.   &wrappedPrivKey, NULL);
  737.     PK11_FreeSymKey(symKey);
  738.     if (rv != SECSuccess) {
  739.         goto loser;
  740.     }
  741.     /* Make the length of the result a Bit String length. */
  742.     wrappedPrivKey.len <<= 3;
  743.     rv = crmf_make_bitstring_copy(NULL, 
  744.   &destValue->encValue, 
  745.   &wrappedPrivKey);
  746.     if (rv != SECSuccess) {
  747.         goto loser;
  748.     }
  749.     rv = crmf_make_bitstring_copy(NULL,
  750.   &destValue->encSymmKey, 
  751.   &wrappedSymKey);
  752.     if (rv != SECSuccess) {
  753.         goto loser;
  754.     }
  755.     destValue->symmAlg = symmAlg = PORT_ZNew(SECAlgorithmID);
  756.     if (symmAlg == NULL) {
  757.         goto loser;
  758.     }
  759.     dummy = SEC_ASN1EncodeItem(NULL, &encodedParam, iv, 
  760.        SEC_OctetStringTemplate);
  761.     if (dummy != &encodedParam) {
  762.         SECITEM_FreeItem(dummy, PR_TRUE);
  763. goto loser;
  764.     }
  765.     symKeyType = crmf_get_non_pad_mechanism(symKeyType);
  766.     tag = PK11_MechanismToAlgtag(symKeyType);
  767.     rv = SECOID_SetAlgorithmID(NULL, symmAlg, tag, &encodedParam);
  768.     if (rv != SECSuccess) {
  769.         goto loser;
  770.     }
  771.     PORT_Free(encodedParam.data);
  772.     PORT_Free(wrappedPrivKeyBits);
  773.     PORT_Free(wrappedSymKeyBits);
  774.     if (iv->data != NULL) {
  775.         PORT_Free(iv->data);
  776.     }
  777.     PORT_Free(iv);
  778.     return destValue;
  779.  loser:
  780.     if (iv != NULL) {
  781.         if (iv->data) {
  782.     PORT_Free(iv->data);
  783. }
  784.         PORT_Free(iv);
  785.     }
  786.     if (myEncrValue != NULL) {
  787.         crmf_destroy_encrypted_value(myEncrValue, PR_TRUE);
  788.     }
  789.     if (wrappedSymKeyBits != NULL) {
  790.         PORT_Free(wrappedSymKeyBits);
  791.     }
  792.     if (wrappedPrivKeyBits != NULL) {
  793.         PORT_Free(wrappedPrivKeyBits);
  794.     }
  795.     if (encodedParam.data != NULL) {
  796.         PORT_Free(encodedParam.data);
  797.     }
  798.     return NULL;
  799. }
  800. CRMFEncryptedKey*
  801. CRMF_CreateEncryptedKeyWithEncryptedValue (SECKEYPrivateKey *inPrivKey,
  802.    CERTCertificate  *inCACert)
  803. {
  804.     SECKEYPublicKey          *caPubKey = NULL;
  805.     CRMFEncryptedKey         *encKey = NULL;
  806.     CRMFEncryptedValue       *dummy;
  807.     PORT_Assert(inPrivKey != NULL && inCACert != NULL);
  808.     if (inPrivKey == NULL || inCACert == NULL) {
  809.         return NULL;
  810.     }
  811.     caPubKey = CERT_ExtractPublicKey(inCACert);
  812.     if (caPubKey == NULL) {
  813.         goto loser;
  814.     }
  815.     encKey = PORT_ZNew(CRMFEncryptedKey);
  816.     if (encKey == NULL) {
  817.         goto loser;
  818.     }
  819.     dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey,
  820. caPubKey,
  821.        &encKey->value.encryptedValue);
  822.     PORT_Assert(dummy == &encKey->value.encryptedValue);
  823.     /* We won't add the der value here, but rather when it 
  824.      * becomes part of a certificate request.
  825.      */
  826.     SECKEY_DestroyPublicKey(caPubKey);
  827.     encKey->encKeyChoice = crmfEncryptedValueChoice;
  828.     return encKey;
  829.  loser:
  830.     if (encKey != NULL) {
  831.         CRMF_DestroyEncryptedKey(encKey);
  832.     }
  833.     if (caPubKey != NULL) {
  834.         SECKEY_DestroyPublicKey(caPubKey);
  835.     }
  836.     return NULL;
  837. }
  838. SECStatus
  839. CRMF_DestroyEncryptedKey(CRMFEncryptedKey *inEncrKey)
  840. {
  841.     return crmf_destroy_encrypted_key(inEncrKey, PR_TRUE);
  842. }
  843. SECStatus
  844. crmf_copy_pkiarchiveoptions(PRArenaPool           *poolp,
  845.     CRMFPKIArchiveOptions *destOpt,
  846.     CRMFPKIArchiveOptions *srcOpt)
  847. {
  848.     SECStatus rv;
  849.     destOpt->archOption = srcOpt->archOption;
  850.     switch (srcOpt->archOption) {
  851.     case crmfEncryptedPrivateKey:
  852.         rv = crmf_copy_encryptedkey(poolp,
  853.     &srcOpt->option.encryptedKey,
  854.     &destOpt->option.encryptedKey);
  855.         break;
  856.     case crmfKeyGenParameters:
  857.     case crmfArchiveRemGenPrivKey:
  858.         /* We've got a union, so having a pointer to one is just
  859.  * like having a pointer to the other one.
  860.  */
  861.         rv = SECITEM_CopyItem(poolp, 
  862.       &destOpt->option.keyGenParameters,
  863.       &srcOpt->option.keyGenParameters);
  864. break;
  865.     default:
  866.         rv = SECFailure;
  867.     }
  868.     return rv;
  869. }
  870. static SECStatus
  871. crmf_check_and_adjust_archoption(CRMFControl *inControl)
  872. {
  873.     CRMFPKIArchiveOptions *options;
  874.     options = &inControl->value.archiveOptions;
  875.     if (options->archOption == crmfNoArchiveOptions) {
  876.         /* It hasn't been set, so figure it out from the 
  877.  * der.
  878.  */
  879.         switch (inControl->derValue.data[0] & 0x0f) {
  880. case 0:
  881.     options->archOption = crmfEncryptedPrivateKey;
  882.     break;
  883. case 1:
  884.     options->archOption = crmfKeyGenParameters;
  885.     break;
  886. case 2:
  887.     options->archOption = crmfArchiveRemGenPrivKey;
  888.     break;
  889. default:
  890.     /* We've got bad DER.  Return an error. */
  891.     return SECFailure;
  892. }
  893.     }
  894.     return SECSuccess;
  895. }
  896. static const SEC_ASN1Template *
  897. crmf_get_pkiarchive_subtemplate(CRMFControl *inControl)
  898. {
  899.     const SEC_ASN1Template *retTemplate;
  900.     SECStatus               rv;
  901.     /*
  902.      * We could be in the process of decoding, in which case the
  903.      * archOption field will not be set.  Let's check it and set 
  904.      * it accordingly.
  905.      */
  906.     rv = crmf_check_and_adjust_archoption(inControl);
  907.     if (rv != SECSuccess) {
  908.         return NULL;
  909.     }
  910.     switch (inControl->value.archiveOptions.archOption) {
  911.     case crmfEncryptedPrivateKey:
  912.         retTemplate = CRMFEncryptedKeyWithEncryptedValueTemplate;
  913. inControl->value.archiveOptions.option.encryptedKey.encKeyChoice =
  914.   crmfEncryptedValueChoice;
  915. break;
  916.     default:
  917.         retTemplate = NULL;
  918.     }
  919.     return retTemplate;
  920. }
  921. const SEC_ASN1Template*
  922. crmf_get_pkiarchiveoptions_subtemplate(CRMFControl *inControl)
  923. {
  924.     const SEC_ASN1Template *retTemplate;
  925.     switch (inControl->tag) {
  926.     case SEC_OID_PKIX_REGCTRL_REGTOKEN:
  927.     case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
  928.         retTemplate = SEC_UTF8StringTemplate;
  929. break;
  930.     case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
  931.         retTemplate = crmf_get_pkiarchive_subtemplate(inControl);
  932. break;
  933.     case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
  934.     case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
  935.     case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
  936.         /* We don't support these controls, so we fail for now.*/
  937.         retTemplate = NULL;
  938. break;
  939.     default:
  940.         retTemplate = NULL;
  941.     }
  942.     return retTemplate;
  943. }
  944. static SECStatus
  945. crmf_encode_pkiarchiveoptions(PRArenaPool *poolp, CRMFControl *inControl)
  946. {
  947.     const SEC_ASN1Template *asn1Template;
  948.     SECStatus               rv;
  949.     asn1Template = crmf_get_pkiarchiveoptions_subtemplate(inControl);
  950.     /* We've got a union, so passing a pointer to one element of the 
  951.      * union, is the same as passing a pointer to any of the other
  952.      * members of the union.
  953.      */
  954.     SEC_ASN1EncodeItem(poolp, &inControl->derValue,
  955.                        &inControl->value.archiveOptions, asn1Template);
  956.     if (inControl->derValue.data == NULL) {
  957.         goto loser;
  958.     }
  959.     return SECSuccess;
  960.  loser:
  961.     return SECFailure;
  962. }
  963. SECStatus
  964. CRMF_CertRequestSetPKIArchiveOptions(CRMFCertRequest       *inCertReq,
  965.      CRMFPKIArchiveOptions *inOptions)
  966. {
  967.     CRMFControl *newControl;
  968.     PRArenaPool *poolp;
  969.     SECStatus    rv;
  970.     void        *mark;
  971.     
  972.     PORT_Assert(inCertReq != NULL && inOptions != NULL);
  973.     if (inCertReq == NULL || inOptions == NULL) {
  974.         return SECFailure;
  975.     }
  976.     poolp = inCertReq->poolp;
  977.     mark = PORT_ArenaMark(poolp);
  978.     rv = crmf_add_new_control(inCertReq, 
  979.       SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS,
  980.       &newControl);
  981.     if (rv != SECSuccess) {
  982.         goto loser;
  983.     }
  984.     rv = crmf_copy_pkiarchiveoptions(poolp, 
  985.      &newControl->value.archiveOptions,
  986.      inOptions);
  987.     if (rv != SECSuccess) {
  988.         goto loser;
  989.     }
  990.     rv = crmf_encode_pkiarchiveoptions(poolp, newControl); 
  991.     if (rv != SECSuccess) {
  992.         goto loser;
  993.     }
  994.     PORT_ArenaUnmark(poolp, mark);
  995.     return SECSuccess;
  996.  loser:
  997.     PORT_ArenaRelease(poolp, mark);
  998.     return SECFailure;
  999. }
  1000. SECStatus
  1001. crmf_destroy_control(CRMFControl *inControl, PRBool freeit)
  1002. {
  1003.     PORT_Assert(inControl != NULL);
  1004.     if (inControl != NULL) {
  1005.         SECITEM_FreeItem(&inControl->derTag, PR_FALSE);
  1006.         SECITEM_FreeItem(&inControl->derValue, PR_FALSE);
  1007. /* None of the other tags require special processing at 
  1008.  * the moment when freeing because they are not supported,
  1009.  * but if/when they are, add the necessary routines here.  
  1010.  * If all controls are supported, then every member of the 
  1011.  * union inControl->value will have a case that deals with 
  1012.  * it in the following switch statement.
  1013.  */
  1014. switch (inControl->tag) {
  1015. case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
  1016.     crmf_destroy_pkiarchiveoptions(&inControl->value.archiveOptions,
  1017.    PR_FALSE);
  1018.     break;
  1019.         default:
  1020.            /* Put this here to get rid of all those annoying warnings.*/
  1021.            break;
  1022. }
  1023. if (freeit) {
  1024.     PORT_Free(inControl);
  1025. }
  1026.     }
  1027.     return SECSuccess;
  1028. }
  1029. SECStatus
  1030. CRMF_DestroyControl(CRMFControl *inControl)
  1031. {
  1032.     return crmf_destroy_control(inControl, PR_TRUE);
  1033. }
  1034. static SECOidTag
  1035. crmf_controltype_to_tag(CRMFControlType inControlType)
  1036. {
  1037.     SECOidTag retVal;
  1038.     switch(inControlType) {
  1039.     case crmfRegTokenControl:
  1040.       retVal = SEC_OID_PKIX_REGCTRL_REGTOKEN; 
  1041.       break;
  1042.     case crmfAuthenticatorControl:
  1043.       retVal = SEC_OID_PKIX_REGCTRL_AUTHENTICATOR;
  1044.       break;
  1045.     case crmfPKIPublicationInfoControl:
  1046.       retVal = SEC_OID_PKIX_REGCTRL_PKIPUBINFO;
  1047.       break;
  1048.     case crmfPKIArchiveOptionsControl:
  1049.       retVal = SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS;
  1050.       break;
  1051.     case crmfOldCertIDControl:
  1052.       retVal = SEC_OID_PKIX_REGCTRL_OLD_CERT_ID;
  1053.       break;
  1054.     case crmfProtocolEncrKeyControl:
  1055.       retVal = SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY;
  1056.       break;
  1057.     default:
  1058.       retVal = SEC_OID_UNKNOWN;
  1059.       break;
  1060.     }
  1061.     return retVal;
  1062. }
  1063. PRBool
  1064. CRMF_CertRequestIsControlPresent(CRMFCertRequest *inCertReq,
  1065.  CRMFControlType  inControlType)
  1066. {
  1067.     SECOidTag controlTag;
  1068.     int       i;
  1069.     PORT_Assert(inCertReq != NULL);
  1070.     if (inCertReq == NULL || inCertReq->controls == NULL) {
  1071.         return PR_FALSE;
  1072.     }
  1073.     controlTag = crmf_controltype_to_tag(inControlType);
  1074.     for (i=0; inCertReq->controls[i] != NULL; i++) {
  1075.         if (inCertReq->controls[i]->tag == controlTag) {
  1076.     return PR_TRUE;
  1077. }
  1078.     }
  1079.     return PR_FALSE;
  1080. }