security/nss/lib/crmf/crmfcont.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/crmf/crmfcont.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1158 @@
     1.4 +/* -*- Mode: C; tab-width: 8 -*-*/
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "crmf.h"
    1.10 +#include "crmfi.h"
    1.11 +#include "pk11func.h"
    1.12 +#include "keyhi.h"
    1.13 +#include "secoid.h"
    1.14 +
    1.15 +static SECStatus
    1.16 +crmf_modify_control_array (CRMFCertRequest *inCertReq, int count)
    1.17 +{
    1.18 +    if (count > 0) {
    1.19 +        void *dummy = PORT_Realloc(inCertReq->controls, 
    1.20 +				   sizeof(CRMFControl*)*(count+2));
    1.21 +	if (dummy == NULL) {
    1.22 +	    return SECFailure;
    1.23 +	}
    1.24 +	inCertReq->controls = dummy;
    1.25 +    } else {
    1.26 +        inCertReq->controls = PORT_ZNewArray(CRMFControl*, 2);
    1.27 +    }
    1.28 +    return (inCertReq->controls == NULL) ? SECFailure : SECSuccess ;
    1.29 +}
    1.30 +
    1.31 +static SECStatus
    1.32 +crmf_add_new_control(CRMFCertRequest *inCertReq,SECOidTag inTag,
    1.33 +		     CRMFControl **destControl)
    1.34 +{
    1.35 +    SECOidData  *oidData;
    1.36 +    SECStatus    rv;
    1.37 +    PLArenaPool *poolp;
    1.38 +    int          numControls = 0;
    1.39 +    CRMFControl *newControl;
    1.40 +    CRMFControl **controls;
    1.41 +    void        *mark;
    1.42 +
    1.43 +    poolp = inCertReq->poolp;
    1.44 +    if (poolp == NULL) {
    1.45 +        return SECFailure;
    1.46 +    }
    1.47 +    mark = PORT_ArenaMark(poolp);
    1.48 +    if (inCertReq->controls != NULL) {
    1.49 +        while (inCertReq->controls[numControls] != NULL)
    1.50 +	    numControls++;
    1.51 +    }
    1.52 +    rv = crmf_modify_control_array(inCertReq, numControls);
    1.53 +    if (rv != SECSuccess) {
    1.54 +        goto loser;
    1.55 +    }
    1.56 +    controls = inCertReq->controls;
    1.57 +    oidData = SECOID_FindOIDByTag(inTag);
    1.58 +    newControl = *destControl = PORT_ArenaZNew(poolp,CRMFControl);
    1.59 +    if (newControl == NULL) {
    1.60 +        goto loser;
    1.61 +    }
    1.62 +    rv = SECITEM_CopyItem(poolp, &newControl->derTag, &oidData->oid);
    1.63 +    if (rv != SECSuccess) {
    1.64 +        goto loser;
    1.65 +    }
    1.66 +    newControl->tag = inTag;
    1.67 +    controls[numControls] = newControl;
    1.68 +    controls[numControls+1] = NULL;
    1.69 +    PORT_ArenaUnmark(poolp, mark);
    1.70 +    return SECSuccess;
    1.71 +
    1.72 + loser:
    1.73 +    PORT_ArenaRelease(poolp, mark);
    1.74 +    *destControl = NULL;
    1.75 +    return SECFailure;
    1.76 +			  
    1.77 +}
    1.78 +
    1.79 +static SECStatus
    1.80 +crmf_add_secitem_control(CRMFCertRequest *inCertReq, SECItem *value,
    1.81 +			 SECOidTag inTag)
    1.82 +{
    1.83 +    SECStatus    rv;
    1.84 +    CRMFControl *newControl;
    1.85 +    void        *mark;
    1.86 +
    1.87 +    rv = crmf_add_new_control(inCertReq, inTag, &newControl);
    1.88 +    if (rv != SECSuccess) {
    1.89 +        return rv;
    1.90 +    }
    1.91 +    mark = PORT_ArenaMark(inCertReq->poolp);
    1.92 +    rv = SECITEM_CopyItem(inCertReq->poolp, &newControl->derValue, value);
    1.93 +    if (rv != SECSuccess) {
    1.94 +        PORT_ArenaRelease(inCertReq->poolp, mark);
    1.95 +	return rv;
    1.96 +    }
    1.97 +    PORT_ArenaUnmark(inCertReq->poolp, mark);
    1.98 +    return SECSuccess;
    1.99 +}
   1.100 +
   1.101 +SECStatus
   1.102 +CRMF_CertRequestSetRegTokenControl(CRMFCertRequest *inCertReq, SECItem *value)
   1.103 +{
   1.104 +    return crmf_add_secitem_control(inCertReq, value, 
   1.105 +				    SEC_OID_PKIX_REGCTRL_REGTOKEN);
   1.106 +}
   1.107 +
   1.108 +SECStatus
   1.109 +CRMF_CertRequestSetAuthenticatorControl (CRMFCertRequest *inCertReq, 
   1.110 +					 SECItem         *value)
   1.111 +{
   1.112 +    return crmf_add_secitem_control(inCertReq, value, 
   1.113 +				    SEC_OID_PKIX_REGCTRL_AUTHENTICATOR);
   1.114 +}
   1.115 +
   1.116 +SECStatus
   1.117 +crmf_destroy_encrypted_value(CRMFEncryptedValue *inEncrValue, PRBool freeit)
   1.118 +{
   1.119 +    if (inEncrValue != NULL) {
   1.120 +        if (inEncrValue->intendedAlg) {
   1.121 +	    SECOID_DestroyAlgorithmID(inEncrValue->intendedAlg, PR_TRUE);
   1.122 +	    inEncrValue->intendedAlg = NULL;
   1.123 +	}
   1.124 +	if (inEncrValue->symmAlg) {
   1.125 +	    SECOID_DestroyAlgorithmID(inEncrValue->symmAlg, PR_TRUE);
   1.126 +	    inEncrValue->symmAlg = NULL;
   1.127 +	}
   1.128 +        if (inEncrValue->encSymmKey.data) {
   1.129 +	    PORT_Free(inEncrValue->encSymmKey.data);
   1.130 +	    inEncrValue->encSymmKey.data = NULL;
   1.131 +	}
   1.132 +	if (inEncrValue->keyAlg) {
   1.133 +	    SECOID_DestroyAlgorithmID(inEncrValue->keyAlg, PR_TRUE);
   1.134 +	    inEncrValue->keyAlg = NULL;
   1.135 +	}
   1.136 +	if (inEncrValue->valueHint.data) {
   1.137 +	    PORT_Free(inEncrValue->valueHint.data);
   1.138 +	    inEncrValue->valueHint.data = NULL;
   1.139 +	}
   1.140 +        if (inEncrValue->encValue.data) {
   1.141 +	    PORT_Free(inEncrValue->encValue.data);
   1.142 +	    inEncrValue->encValue.data = NULL;
   1.143 +	}
   1.144 +	if (freeit) {
   1.145 +	    PORT_Free(inEncrValue);
   1.146 +	}
   1.147 +    }
   1.148 +    return SECSuccess;
   1.149 +}
   1.150 +
   1.151 +SECStatus
   1.152 +CRMF_DestroyEncryptedValue(CRMFEncryptedValue *inEncrValue)
   1.153 +{
   1.154 +    return crmf_destroy_encrypted_value(inEncrValue, PR_TRUE);
   1.155 +}
   1.156 +
   1.157 +SECStatus
   1.158 +crmf_copy_encryptedvalue_secalg(PLArenaPool     *poolp,
   1.159 +				SECAlgorithmID  *srcAlgId,
   1.160 +				SECAlgorithmID **destAlgId)
   1.161 +{
   1.162 +    SECAlgorithmID *newAlgId;
   1.163 +    SECStatus rv;
   1.164 +
   1.165 +    newAlgId = (poolp != NULL) ? PORT_ArenaZNew(poolp, SECAlgorithmID) :
   1.166 +                                 PORT_ZNew(SECAlgorithmID);
   1.167 +    if (newAlgId == NULL) {
   1.168 +        return SECFailure;
   1.169 +    }
   1.170 +    
   1.171 +    rv = SECOID_CopyAlgorithmID(poolp, newAlgId, srcAlgId);
   1.172 +    if (rv != SECSuccess) {
   1.173 +        if (!poolp) {
   1.174 +            SECOID_DestroyAlgorithmID(newAlgId, PR_TRUE);
   1.175 +        }
   1.176 +        return rv;
   1.177 +    }
   1.178 +    *destAlgId = newAlgId;
   1.179 +    
   1.180 +    return rv;
   1.181 +}
   1.182 +
   1.183 +SECStatus
   1.184 +crmf_copy_encryptedvalue(PLArenaPool        *poolp,
   1.185 +			 CRMFEncryptedValue *srcValue,
   1.186 +			 CRMFEncryptedValue *destValue)
   1.187 +{
   1.188 +    SECStatus           rv;
   1.189 +
   1.190 +    if (srcValue->intendedAlg != NULL) {
   1.191 +        rv = crmf_copy_encryptedvalue_secalg(poolp,
   1.192 +					     srcValue->intendedAlg,
   1.193 +					     &destValue->intendedAlg);
   1.194 +	if (rv != SECSuccess) {
   1.195 +	    goto loser;
   1.196 +	}
   1.197 +    }
   1.198 +    if (srcValue->symmAlg != NULL) {
   1.199 +        rv = crmf_copy_encryptedvalue_secalg(poolp, 
   1.200 +					     srcValue->symmAlg,
   1.201 +					     &destValue->symmAlg);
   1.202 +	if (rv != SECSuccess) {
   1.203 +	    goto loser;
   1.204 +	}
   1.205 +    }
   1.206 +    if (srcValue->encSymmKey.data != NULL) {
   1.207 +        rv = crmf_make_bitstring_copy(poolp, 
   1.208 +				      &destValue->encSymmKey,
   1.209 +				      &srcValue->encSymmKey);
   1.210 +	if (rv != SECSuccess) {
   1.211 +	    goto loser;
   1.212 +	}
   1.213 +    }
   1.214 +    if (srcValue->keyAlg != NULL) {
   1.215 +        rv = crmf_copy_encryptedvalue_secalg(poolp,
   1.216 +					     srcValue->keyAlg,
   1.217 +					     &destValue->keyAlg);
   1.218 +	if (rv != SECSuccess) {
   1.219 +	    goto loser;
   1.220 +	}
   1.221 +    }
   1.222 +    if (srcValue->valueHint.data != NULL) {
   1.223 +        rv = SECITEM_CopyItem(poolp, 
   1.224 +			      &destValue->valueHint,
   1.225 +			      &srcValue->valueHint);
   1.226 +	if (rv != SECSuccess) {
   1.227 +	    goto loser;
   1.228 +	}
   1.229 +    }
   1.230 +    if (srcValue->encValue.data != NULL) {
   1.231 +        rv = crmf_make_bitstring_copy(poolp,
   1.232 +				      &destValue->encValue,
   1.233 +				      &srcValue->encValue);
   1.234 +	if (rv != SECSuccess) {
   1.235 +	    goto loser;
   1.236 +	}
   1.237 +    }
   1.238 +    return SECSuccess;
   1.239 + loser:
   1.240 +    if (poolp == NULL && destValue != NULL) {
   1.241 +        crmf_destroy_encrypted_value(destValue, PR_FALSE);
   1.242 +    }
   1.243 +    return SECFailure;
   1.244 +}
   1.245 +
   1.246 +SECStatus 
   1.247 +crmf_copy_encryptedkey(PLArenaPool       *poolp,
   1.248 +		       CRMFEncryptedKey  *srcEncrKey,
   1.249 +		       CRMFEncryptedKey  *destEncrKey)
   1.250 +{
   1.251 +    SECStatus          rv;
   1.252 +    void              *mark = NULL;
   1.253 +
   1.254 +    if (poolp != NULL) {
   1.255 +        mark = PORT_ArenaMark(poolp);
   1.256 +    }
   1.257 +
   1.258 +    switch (srcEncrKey->encKeyChoice) {
   1.259 +    case crmfEncryptedValueChoice:
   1.260 +        rv = crmf_copy_encryptedvalue(poolp, 
   1.261 +				      &srcEncrKey->value.encryptedValue,
   1.262 +				      &destEncrKey->value.encryptedValue);
   1.263 +	break;
   1.264 +    case crmfEnvelopedDataChoice:
   1.265 +        destEncrKey->value.envelopedData = 
   1.266 +	    SEC_PKCS7CopyContentInfo(srcEncrKey->value.envelopedData);
   1.267 +        rv = (destEncrKey->value.envelopedData != NULL) ? SECSuccess:
   1.268 +	                                                  SECFailure;
   1.269 +        break;
   1.270 +    default:
   1.271 +        rv = SECFailure;
   1.272 +    }
   1.273 +    if (rv != SECSuccess) {
   1.274 +        goto loser;
   1.275 +    }
   1.276 +    destEncrKey->encKeyChoice = srcEncrKey->encKeyChoice;
   1.277 +    if (mark) {
   1.278 +    	PORT_ArenaUnmark(poolp, mark);
   1.279 +    }
   1.280 +    return SECSuccess;
   1.281 +
   1.282 + loser:
   1.283 +    if (mark) {
   1.284 +        PORT_ArenaRelease(poolp, mark);
   1.285 +    }
   1.286 +    return SECFailure;
   1.287 +}
   1.288 +
   1.289 +static CRMFPKIArchiveOptions*
   1.290 +crmf_create_encr_pivkey_option(CRMFEncryptedKey *inEncryptedKey)
   1.291 +{
   1.292 +    CRMFPKIArchiveOptions *newArchOpt;
   1.293 +    SECStatus              rv;
   1.294 +
   1.295 +    newArchOpt = PORT_ZNew(CRMFPKIArchiveOptions);
   1.296 +    if (newArchOpt == NULL) {
   1.297 +        goto loser;
   1.298 +    }
   1.299 +
   1.300 +    rv = crmf_copy_encryptedkey(NULL, inEncryptedKey,
   1.301 +				&newArchOpt->option.encryptedKey);
   1.302 +    
   1.303 +    if (rv != SECSuccess) {
   1.304 +      goto loser;
   1.305 +    }
   1.306 +    newArchOpt->archOption = crmfEncryptedPrivateKey;
   1.307 +    return newArchOpt;
   1.308 + loser:
   1.309 +    if (newArchOpt != NULL) {
   1.310 +        CRMF_DestroyPKIArchiveOptions(newArchOpt);
   1.311 +    }
   1.312 +    return NULL;
   1.313 +}
   1.314 +
   1.315 +static CRMFPKIArchiveOptions*
   1.316 +crmf_create_keygen_param_option(SECItem *inKeyGenParams)
   1.317 +{
   1.318 +    CRMFPKIArchiveOptions *newArchOptions;
   1.319 +    SECStatus              rv;
   1.320 +
   1.321 +    newArchOptions = PORT_ZNew(CRMFPKIArchiveOptions);
   1.322 +    if (newArchOptions == NULL) {
   1.323 +        goto loser;
   1.324 +    }
   1.325 +    newArchOptions->archOption = crmfKeyGenParameters;
   1.326 +    rv = SECITEM_CopyItem(NULL, &newArchOptions->option.keyGenParameters,
   1.327 +			  inKeyGenParams);
   1.328 +    if (rv != SECSuccess) {
   1.329 +        goto loser;
   1.330 +    }
   1.331 +    return newArchOptions;
   1.332 + loser:
   1.333 +    if (newArchOptions != NULL) {
   1.334 +        CRMF_DestroyPKIArchiveOptions(newArchOptions);
   1.335 +    }
   1.336 +    return NULL;
   1.337 +}
   1.338 +
   1.339 +static CRMFPKIArchiveOptions*
   1.340 +crmf_create_arch_rem_gen_privkey(PRBool archiveRemGenPrivKey)
   1.341 +{
   1.342 +    unsigned char          value;
   1.343 +    SECItem               *dummy;
   1.344 +    CRMFPKIArchiveOptions *newArchOptions;
   1.345 +
   1.346 +    value = (archiveRemGenPrivKey) ? hexTrue : hexFalse;
   1.347 +    newArchOptions = PORT_ZNew(CRMFPKIArchiveOptions);
   1.348 +    if (newArchOptions == NULL) {
   1.349 +        goto loser;
   1.350 +    }
   1.351 +    dummy = SEC_ASN1EncodeItem(NULL, 
   1.352 +			       &newArchOptions->option.archiveRemGenPrivKey,
   1.353 +			       &value, SEC_ASN1_GET(SEC_BooleanTemplate));
   1.354 +    PORT_Assert (dummy == &newArchOptions->option.archiveRemGenPrivKey);
   1.355 +    if (dummy != &newArchOptions->option.archiveRemGenPrivKey) {
   1.356 +        SECITEM_FreeItem (dummy, PR_TRUE);
   1.357 +	goto loser;
   1.358 +    }
   1.359 +    newArchOptions->archOption = crmfArchiveRemGenPrivKey;
   1.360 +    return newArchOptions;
   1.361 + loser:
   1.362 +    if (newArchOptions != NULL) {
   1.363 +        CRMF_DestroyPKIArchiveOptions(newArchOptions);
   1.364 +    }
   1.365 +    return NULL;
   1.366 +}
   1.367 +
   1.368 +CRMFPKIArchiveOptions*
   1.369 +CRMF_CreatePKIArchiveOptions(CRMFPKIArchiveOptionsType inType, void *data)
   1.370 +{
   1.371 +    CRMFPKIArchiveOptions* retOptions;
   1.372 +
   1.373 +    PORT_Assert(data != NULL);
   1.374 +    if (data == NULL) {
   1.375 +        return NULL;
   1.376 +    }
   1.377 +    switch(inType) {
   1.378 +    case crmfEncryptedPrivateKey:
   1.379 +        retOptions = crmf_create_encr_pivkey_option((CRMFEncryptedKey*)data);
   1.380 +	break;
   1.381 +    case crmfKeyGenParameters:
   1.382 +        retOptions = crmf_create_keygen_param_option((SECItem*)data);
   1.383 +	break;
   1.384 +    case crmfArchiveRemGenPrivKey:
   1.385 +        retOptions = crmf_create_arch_rem_gen_privkey(*(PRBool*)data);
   1.386 +	break;
   1.387 +    default:
   1.388 +        retOptions = NULL;
   1.389 +    }
   1.390 +    return retOptions;
   1.391 +}
   1.392 +
   1.393 +static SECStatus
   1.394 +crmf_destroy_encrypted_key(CRMFEncryptedKey *inEncrKey, PRBool freeit)
   1.395 +{ 
   1.396 +    PORT_Assert(inEncrKey != NULL);
   1.397 +    if (inEncrKey != NULL) {
   1.398 +        switch (inEncrKey->encKeyChoice){
   1.399 +	case crmfEncryptedValueChoice:
   1.400 +            crmf_destroy_encrypted_value(&inEncrKey->value.encryptedValue, 
   1.401 +					 PR_FALSE);
   1.402 +	    break;
   1.403 +	case crmfEnvelopedDataChoice:
   1.404 +	    SEC_PKCS7DestroyContentInfo(inEncrKey->value.envelopedData);
   1.405 +            break;
   1.406 +        default:
   1.407 +            break;
   1.408 +        }
   1.409 +        if (freeit) {
   1.410 +            PORT_Free(inEncrKey);
   1.411 +        }
   1.412 +    }
   1.413 +    return SECSuccess;
   1.414 +}
   1.415 +
   1.416 +SECStatus 
   1.417 +crmf_destroy_pkiarchiveoptions(CRMFPKIArchiveOptions *inArchOptions, 
   1.418 +			       PRBool                 freeit)
   1.419 +{
   1.420 +    PORT_Assert(inArchOptions != NULL);
   1.421 +    if (inArchOptions != NULL) {
   1.422 +        switch (inArchOptions->archOption) {
   1.423 +	case crmfEncryptedPrivateKey:
   1.424 +	    crmf_destroy_encrypted_key(&inArchOptions->option.encryptedKey,
   1.425 +				       PR_FALSE);
   1.426 +	    break;
   1.427 +	case crmfKeyGenParameters:
   1.428 +	case crmfArchiveRemGenPrivKey:
   1.429 +	    /* This is a union, so having a pointer to one is like
   1.430 +	     * having a pointer to both.  
   1.431 +	     */
   1.432 +	    SECITEM_FreeItem(&inArchOptions->option.keyGenParameters, 
   1.433 +			     PR_FALSE);
   1.434 +	    break;
   1.435 +        case crmfNoArchiveOptions:
   1.436 +            break;
   1.437 +	}
   1.438 +	if (freeit) {
   1.439 +	    PORT_Free(inArchOptions);
   1.440 +	}
   1.441 +    }
   1.442 +    return SECSuccess;
   1.443 +}
   1.444 +
   1.445 +SECStatus
   1.446 +CRMF_DestroyPKIArchiveOptions(CRMFPKIArchiveOptions *inArchOptions) 
   1.447 +{
   1.448 +    return crmf_destroy_pkiarchiveoptions(inArchOptions, PR_TRUE);
   1.449 +}
   1.450 +
   1.451 +static CK_MECHANISM_TYPE
   1.452 +crmf_get_non_pad_mechanism(CK_MECHANISM_TYPE type)
   1.453 +{
   1.454 +    switch (type) {
   1.455 +    case CKM_DES3_CBC_PAD:
   1.456 +        return CKM_DES3_CBC;
   1.457 +    case CKM_CAST5_CBC_PAD:
   1.458 +        return CKM_CAST5_CBC;
   1.459 +    case CKM_DES_CBC_PAD:
   1.460 +        return CKM_DES_CBC;
   1.461 +    case CKM_IDEA_CBC_PAD:
   1.462 +        return CKM_IDEA_CBC;
   1.463 +    case CKM_CAST3_CBC_PAD:
   1.464 +        return CKM_CAST3_CBC;
   1.465 +    case CKM_CAST_CBC_PAD:
   1.466 +        return CKM_CAST_CBC;
   1.467 +    case CKM_RC5_CBC_PAD:
   1.468 +        return CKM_RC5_CBC;
   1.469 +    case CKM_RC2_CBC_PAD:
   1.470 +        return CKM_RC2_CBC;
   1.471 +    case CKM_CDMF_CBC_PAD:
   1.472 +        return CKM_CDMF_CBC;
   1.473 +    }
   1.474 +    return type;
   1.475 +}
   1.476 +
   1.477 +static CK_MECHANISM_TYPE
   1.478 +crmf_get_pad_mech_from_tag(SECOidTag oidTag)
   1.479 +{
   1.480 +    CK_MECHANISM_TYPE  mechType;
   1.481 +    SECOidData        *oidData;
   1.482 +
   1.483 +    oidData = SECOID_FindOIDByTag(oidTag);
   1.484 +    mechType = (CK_MECHANISM_TYPE)oidData->mechanism;
   1.485 +    return PK11_GetPadMechanism(mechType);
   1.486 +}
   1.487 +
   1.488 +static CK_MECHANISM_TYPE
   1.489 +crmf_get_best_privkey_wrap_mechanism(PK11SlotInfo *slot) 
   1.490 +{
   1.491 +    CK_MECHANISM_TYPE privKeyPadMechs[] = { CKM_DES3_CBC_PAD,
   1.492 +					    CKM_CAST5_CBC_PAD,
   1.493 +					    CKM_DES_CBC_PAD,
   1.494 +					    CKM_IDEA_CBC_PAD,
   1.495 +					    CKM_CAST3_CBC_PAD,
   1.496 +					    CKM_CAST_CBC_PAD,
   1.497 +					    CKM_RC5_CBC_PAD,
   1.498 +					    CKM_RC2_CBC_PAD,
   1.499 +					    CKM_CDMF_CBC_PAD };
   1.500 +    int mechCount = sizeof(privKeyPadMechs)/sizeof(privKeyPadMechs[0]);
   1.501 +    int i;
   1.502 +
   1.503 +    for (i=0; i < mechCount; i++) {
   1.504 +        if (PK11_DoesMechanism(slot, privKeyPadMechs[i])) {
   1.505 +	    return privKeyPadMechs[i];
   1.506 +	}
   1.507 +    }
   1.508 +    return CKM_INVALID_MECHANISM;
   1.509 +}
   1.510 +
   1.511 +CK_MECHANISM_TYPE
   1.512 +CRMF_GetBestWrapPadMechanism(PK11SlotInfo *slot)
   1.513 +{
   1.514 +    return crmf_get_best_privkey_wrap_mechanism(slot);
   1.515 +}
   1.516 +
   1.517 +static SECItem*
   1.518 +crmf_get_iv(CK_MECHANISM_TYPE mechType)
   1.519 +{
   1.520 +    int        iv_size = PK11_GetIVLength(mechType);
   1.521 +    SECItem   *iv;
   1.522 +    SECStatus  rv; 
   1.523 +
   1.524 +    iv = PORT_ZNew(SECItem);
   1.525 +    if (iv == NULL) {
   1.526 +        return NULL;
   1.527 +    }
   1.528 +    if (iv_size == 0) {
   1.529 +        iv->data = NULL;
   1.530 +	iv->len  = 0;
   1.531 +	return iv;
   1.532 +    }
   1.533 +    iv->data = PORT_NewArray(unsigned char, iv_size);
   1.534 +    if (iv->data == NULL) {
   1.535 +        iv->len = 0;
   1.536 +	return iv;
   1.537 +    }
   1.538 +    iv->len = iv_size;
   1.539 +    rv = PK11_GenerateRandom(iv->data, iv->len);
   1.540 +    if (rv != SECSuccess) {
   1.541 +        PORT_Free(iv->data);
   1.542 +	iv->data = NULL;
   1.543 +	iv->len  = 0;
   1.544 +    }
   1.545 +    return iv;
   1.546 +}
   1.547 +
   1.548 +SECItem*
   1.549 +CRMF_GetIVFromMechanism(CK_MECHANISM_TYPE mechType)
   1.550 +{
   1.551 +    return crmf_get_iv(mechType);
   1.552 +}
   1.553 +
   1.554 +CK_MECHANISM_TYPE
   1.555 +crmf_get_mechanism_from_public_key(SECKEYPublicKey *inPubKey)
   1.556 +{
   1.557 +    CERTSubjectPublicKeyInfo *spki = NULL;
   1.558 +    SECOidTag                 tag;
   1.559 +    
   1.560 +
   1.561 +    spki = SECKEY_CreateSubjectPublicKeyInfo(inPubKey);
   1.562 +    if (spki == NULL) {
   1.563 +        return CKM_INVALID_MECHANISM;
   1.564 +    }
   1.565 +    tag = SECOID_FindOIDTag(&spki->algorithm.algorithm);
   1.566 +    SECKEY_DestroySubjectPublicKeyInfo(spki);
   1.567 +    spki = NULL;
   1.568 +    return PK11_AlgtagToMechanism(tag);
   1.569 +}
   1.570 +
   1.571 +SECItem*
   1.572 +crmf_get_public_value(SECKEYPublicKey *pubKey, SECItem *dest)
   1.573 +{
   1.574 +    SECItem *src;
   1.575 +
   1.576 +    switch(pubKey->keyType) {
   1.577 +    case dsaKey:
   1.578 +	src =  &pubKey->u.dsa.publicValue;
   1.579 +	break;
   1.580 +    case rsaKey:
   1.581 +	src =  &pubKey->u.rsa.modulus;
   1.582 +	break;
   1.583 +    case dhKey:
   1.584 +	src =  &pubKey->u.dh.publicValue;
   1.585 +	break;
   1.586 +    default:
   1.587 +	src = NULL;
   1.588 +	break;
   1.589 +    }
   1.590 +    if (!src) {
   1.591 +	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1.592 +	return NULL;
   1.593 +    }
   1.594 +
   1.595 +    if (dest != NULL) {
   1.596 +	SECStatus rv = SECITEM_CopyItem(NULL, dest, src);
   1.597 +	if (rv != SECSuccess) {
   1.598 +	    dest = NULL;
   1.599 +	}
   1.600 +    } else {
   1.601 +        dest = SECITEM_ArenaDupItem(NULL, src);
   1.602 +    }
   1.603 +    return dest;
   1.604 +}
   1.605 +
   1.606 +static SECItem*
   1.607 +crmf_decode_params(SECItem *inParams)
   1.608 +{
   1.609 +    SECItem     *params;
   1.610 +    SECStatus    rv      = SECFailure;
   1.611 +    PLArenaPool *poolp;
   1.612 +
   1.613 +    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
   1.614 +    if (poolp == NULL) {
   1.615 +        return NULL;
   1.616 +    }
   1.617 +    
   1.618 +    params = PORT_ArenaZNew(poolp, SECItem);
   1.619 +    if (params) {
   1.620 +	rv = SEC_ASN1DecodeItem(poolp, params, 
   1.621 +				SEC_ASN1_GET(SEC_OctetStringTemplate),
   1.622 +				inParams);
   1.623 +    }
   1.624 +    params = (rv == SECSuccess) ? SECITEM_ArenaDupItem(NULL, params) : NULL;
   1.625 +    PORT_FreeArena(poolp, PR_FALSE);
   1.626 +    return params;
   1.627 +}
   1.628 +
   1.629 +static int
   1.630 +crmf_get_key_size_from_mech(CK_MECHANISM_TYPE mechType)
   1.631 +{
   1.632 +    CK_MECHANISM_TYPE keyGen = PK11_GetKeyGen(mechType);
   1.633 +
   1.634 +    switch (keyGen) {
   1.635 +    case CKM_CDMF_KEY_GEN:
   1.636 +    case CKM_DES_KEY_GEN:
   1.637 +        return 8;
   1.638 +    case CKM_DES2_KEY_GEN:
   1.639 +	return 16;
   1.640 +    case CKM_DES3_KEY_GEN:
   1.641 +	return 24;
   1.642 +    }
   1.643 +    return 0;
   1.644 +}
   1.645 +
   1.646 +SECStatus
   1.647 +crmf_encrypted_value_unwrap_priv_key(PLArenaPool        *poolp,
   1.648 +				     CRMFEncryptedValue *encValue,
   1.649 +				     SECKEYPrivateKey   *privKey,
   1.650 +				     SECKEYPublicKey    *newPubKey,
   1.651 +				     SECItem            *nickname,
   1.652 +				     PK11SlotInfo       *slot,
   1.653 +				     unsigned char       keyUsage,
   1.654 +				     SECKEYPrivateKey  **unWrappedKey,
   1.655 +				     void               *wincx)
   1.656 +{
   1.657 +    PK11SymKey        *wrappingKey = NULL;
   1.658 +    CK_MECHANISM_TYPE  wrapMechType;
   1.659 +    SECOidTag          oidTag;
   1.660 +    SECItem           *params = NULL, *publicValue = NULL;
   1.661 +    int                keySize, origLen;
   1.662 +    CK_KEY_TYPE        keyType;
   1.663 +    CK_ATTRIBUTE_TYPE *usage = NULL;
   1.664 +    CK_ATTRIBUTE_TYPE rsaUsage[] = {
   1.665 +      CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER };
   1.666 +    CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN };
   1.667 +    CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE };
   1.668 +    int usageCount = 0;
   1.669 +
   1.670 +    oidTag = SECOID_GetAlgorithmTag(encValue->symmAlg);
   1.671 +    wrapMechType = crmf_get_pad_mech_from_tag(oidTag);
   1.672 +    keySize = crmf_get_key_size_from_mech(wrapMechType);
   1.673 +    wrappingKey = PK11_PubUnwrapSymKey(privKey, &encValue->encSymmKey, 
   1.674 +				       wrapMechType, CKA_UNWRAP, keySize);
   1.675 +    if (wrappingKey == NULL) {
   1.676 +        goto loser;
   1.677 +    }/* Make the length a byte length instead of bit length*/
   1.678 +    params = (encValue->symmAlg != NULL) ? 
   1.679 +              crmf_decode_params(&encValue->symmAlg->parameters) : NULL;
   1.680 +    origLen = encValue->encValue.len;
   1.681 +    encValue->encValue.len = CRMF_BITS_TO_BYTES(origLen);
   1.682 +    publicValue = crmf_get_public_value(newPubKey, NULL);
   1.683 +    switch(newPubKey->keyType) {
   1.684 +    default:
   1.685 +    case rsaKey:
   1.686 +        keyType = CKK_RSA;
   1.687 +        switch  (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) {
   1.688 +        case KU_KEY_ENCIPHERMENT:
   1.689 +            usage = rsaUsage;
   1.690 +            usageCount = 2;
   1.691 +            break;
   1.692 +        case KU_DIGITAL_SIGNATURE:
   1.693 +            usage = &rsaUsage[2];
   1.694 +            usageCount = 2;
   1.695 +            break;
   1.696 +        case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE:
   1.697 +        case 0: /* default to everything */
   1.698 +            usage = rsaUsage;
   1.699 +            usageCount = 4;
   1.700 +            break;
   1.701 +        }
   1.702 +	break;
   1.703 +    case dhKey:
   1.704 +        keyType = CKK_DH;
   1.705 +        usage = dhUsage;
   1.706 +        usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]);
   1.707 +        break;
   1.708 +    case dsaKey:
   1.709 +        keyType = CKK_DSA;
   1.710 +        usage = dsaUsage;
   1.711 +        usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]);
   1.712 +        break;
   1.713 +    }
   1.714 +    PORT_Assert(usage != NULL);
   1.715 +    PORT_Assert(usageCount != 0);
   1.716 +    *unWrappedKey = PK11_UnwrapPrivKey(slot, wrappingKey, wrapMechType, params,
   1.717 +				       &encValue->encValue, nickname,
   1.718 +				       publicValue, PR_TRUE,PR_TRUE, 
   1.719 +				       keyType, usage, usageCount, wincx);
   1.720 +    encValue->encValue.len = origLen;
   1.721 +    if (*unWrappedKey == NULL) {
   1.722 +        goto loser;
   1.723 +    }
   1.724 +    SECITEM_FreeItem (publicValue, PR_TRUE);
   1.725 +    if (params!= NULL) {
   1.726 +        SECITEM_FreeItem(params, PR_TRUE);
   1.727 +    } 
   1.728 +    PK11_FreeSymKey(wrappingKey);
   1.729 +    return SECSuccess;
   1.730 + loser:
   1.731 +    *unWrappedKey = NULL;
   1.732 +    return SECFailure;
   1.733 +}
   1.734 +
   1.735 +CRMFEncryptedValue *
   1.736 +crmf_create_encrypted_value_wrapped_privkey(SECKEYPrivateKey   *inPrivKey,
   1.737 +					    SECKEYPublicKey    *inCAKey,
   1.738 +					    CRMFEncryptedValue *destValue)
   1.739 +{
   1.740 +    SECItem                   wrappedPrivKey, wrappedSymKey;
   1.741 +    SECItem                   encodedParam, *dummy;
   1.742 +    SECStatus                 rv;
   1.743 +    CK_MECHANISM_TYPE         pubMechType, symKeyType;
   1.744 +    unsigned char            *wrappedSymKeyBits;
   1.745 +    unsigned char            *wrappedPrivKeyBits;
   1.746 +    SECItem                  *iv = NULL;
   1.747 +    SECOidTag                 tag;
   1.748 +    PK11SymKey               *symKey;
   1.749 +    PK11SlotInfo             *slot;
   1.750 +    SECAlgorithmID           *symmAlg;
   1.751 +    CRMFEncryptedValue       *myEncrValue = NULL;
   1.752 +
   1.753 +    encodedParam.data = NULL;
   1.754 +    wrappedSymKeyBits  = PORT_NewArray(unsigned char, MAX_WRAPPED_KEY_LEN);
   1.755 +    wrappedPrivKeyBits = PORT_NewArray(unsigned char, MAX_WRAPPED_KEY_LEN);
   1.756 +    if (wrappedSymKeyBits == NULL || wrappedPrivKeyBits == NULL) {
   1.757 +        goto loser;
   1.758 +    }
   1.759 +    if (destValue == NULL) {
   1.760 +        myEncrValue = destValue = PORT_ZNew(CRMFEncryptedValue);
   1.761 +	if (destValue == NULL) {
   1.762 +	    goto loser;
   1.763 +	}
   1.764 +    }
   1.765 +
   1.766 +    pubMechType = crmf_get_mechanism_from_public_key(inCAKey);
   1.767 +    if (pubMechType == CKM_INVALID_MECHANISM) {
   1.768 +        /* XXX I should probably do something here for non-RSA 
   1.769 +	 *     keys that are in certs. (ie DSA)
   1.770 +	 * XXX or at least SET AN ERROR CODE.
   1.771 +	 */
   1.772 +        goto loser;
   1.773 +    }
   1.774 +    slot = inPrivKey->pkcs11Slot; 
   1.775 +    PORT_Assert(slot != NULL);
   1.776 +    symKeyType = crmf_get_best_privkey_wrap_mechanism(slot);
   1.777 +    symKey = PK11_KeyGen(slot, symKeyType, NULL, 0, NULL);
   1.778 +    if (symKey == NULL) {
   1.779 +        goto loser;
   1.780 +    }
   1.781 +
   1.782 +    wrappedSymKey.data = wrappedSymKeyBits;
   1.783 +    wrappedSymKey.len  = MAX_WRAPPED_KEY_LEN;
   1.784 +    rv = PK11_PubWrapSymKey(pubMechType, inCAKey, symKey, &wrappedSymKey);
   1.785 +    if (rv != SECSuccess) {
   1.786 +        goto loser;
   1.787 +    }
   1.788 +    /* Make the length of the result a Bit String length. */
   1.789 +    wrappedSymKey.len <<= 3;
   1.790 +
   1.791 +    wrappedPrivKey.data = wrappedPrivKeyBits;
   1.792 +    wrappedPrivKey.len  = MAX_WRAPPED_KEY_LEN;
   1.793 +    iv = crmf_get_iv(symKeyType);
   1.794 +    rv = PK11_WrapPrivKey(slot, symKey, inPrivKey, symKeyType, iv, 
   1.795 +			  &wrappedPrivKey, NULL);
   1.796 +    PK11_FreeSymKey(symKey);
   1.797 +    if (rv != SECSuccess) {
   1.798 +        goto loser;
   1.799 +    }
   1.800 +    /* Make the length of the result a Bit String length. */
   1.801 +    wrappedPrivKey.len <<= 3;
   1.802 +    rv = crmf_make_bitstring_copy(NULL, 
   1.803 +				  &destValue->encValue, 
   1.804 +				  &wrappedPrivKey);
   1.805 +    if (rv != SECSuccess) {
   1.806 +        goto loser;
   1.807 +    }
   1.808 +
   1.809 +    rv = crmf_make_bitstring_copy(NULL,
   1.810 +				  &destValue->encSymmKey, 
   1.811 +				  &wrappedSymKey);
   1.812 +    if (rv != SECSuccess) {
   1.813 +        goto loser;
   1.814 +    }
   1.815 +    destValue->symmAlg = symmAlg = PORT_ZNew(SECAlgorithmID);
   1.816 +    if (symmAlg == NULL) {
   1.817 +        goto loser;
   1.818 +    }
   1.819 +
   1.820 +    dummy = SEC_ASN1EncodeItem(NULL, &encodedParam, iv, 
   1.821 +                               SEC_ASN1_GET(SEC_OctetStringTemplate));
   1.822 +    if (dummy != &encodedParam) {
   1.823 +        SECITEM_FreeItem(dummy, PR_TRUE);
   1.824 +	goto loser;
   1.825 +    }
   1.826 +
   1.827 +    symKeyType = crmf_get_non_pad_mechanism(symKeyType);
   1.828 +    tag = PK11_MechanismToAlgtag(symKeyType);
   1.829 +    rv = SECOID_SetAlgorithmID(NULL, symmAlg, tag, &encodedParam);
   1.830 +    if (rv != SECSuccess) {
   1.831 +        goto loser;
   1.832 +    }
   1.833 +    SECITEM_FreeItem(&encodedParam, PR_FALSE);
   1.834 +    PORT_Free(wrappedPrivKeyBits);
   1.835 +    PORT_Free(wrappedSymKeyBits);
   1.836 +    SECITEM_FreeItem(iv, PR_TRUE);
   1.837 +    return destValue;
   1.838 + loser:
   1.839 +    if (iv != NULL) {
   1.840 +	SECITEM_FreeItem(iv, PR_TRUE);
   1.841 +    }
   1.842 +    if (myEncrValue != NULL) {
   1.843 +        crmf_destroy_encrypted_value(myEncrValue, PR_TRUE);
   1.844 +    }
   1.845 +    if (wrappedSymKeyBits != NULL) {
   1.846 +        PORT_Free(wrappedSymKeyBits);
   1.847 +    }
   1.848 +    if (wrappedPrivKeyBits != NULL) {
   1.849 +        PORT_Free(wrappedPrivKeyBits);
   1.850 +    }
   1.851 +    if (encodedParam.data != NULL) {
   1.852 +	SECITEM_FreeItem(&encodedParam, PR_FALSE);
   1.853 +    }
   1.854 +    return NULL;
   1.855 +}
   1.856 +
   1.857 +CRMFEncryptedKey*
   1.858 +CRMF_CreateEncryptedKeyWithEncryptedValue (SECKEYPrivateKey *inPrivKey,
   1.859 +					   CERTCertificate  *inCACert)
   1.860 +{
   1.861 +    SECKEYPublicKey          *caPubKey = NULL;
   1.862 +    CRMFEncryptedKey         *encKey = NULL;
   1.863 +    CRMFEncryptedValue       *dummy;
   1.864 +
   1.865 +    PORT_Assert(inPrivKey != NULL && inCACert != NULL);
   1.866 +    if (inPrivKey == NULL || inCACert == NULL) {
   1.867 +        return NULL;
   1.868 +    }
   1.869 +
   1.870 +    caPubKey = CERT_ExtractPublicKey(inCACert);
   1.871 +    if (caPubKey == NULL) {
   1.872 +        goto loser;
   1.873 +    }
   1.874 +
   1.875 +    encKey = PORT_ZNew(CRMFEncryptedKey);
   1.876 +    if (encKey == NULL) {
   1.877 +        goto loser;
   1.878 +    }
   1.879 +    dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey,
   1.880 +							caPubKey,
   1.881 +					       &encKey->value.encryptedValue);
   1.882 +    PORT_Assert(dummy == &encKey->value.encryptedValue);
   1.883 +    /* We won't add the der value here, but rather when it 
   1.884 +     * becomes part of a certificate request.
   1.885 +     */
   1.886 +    SECKEY_DestroyPublicKey(caPubKey);
   1.887 +    encKey->encKeyChoice = crmfEncryptedValueChoice;
   1.888 +    return encKey;
   1.889 + loser:
   1.890 +    if (encKey != NULL) {
   1.891 +        CRMF_DestroyEncryptedKey(encKey);
   1.892 +    }
   1.893 +    if (caPubKey != NULL) {
   1.894 +        SECKEY_DestroyPublicKey(caPubKey);
   1.895 +    }
   1.896 +    return NULL;
   1.897 +}
   1.898 +
   1.899 +SECStatus
   1.900 +CRMF_DestroyEncryptedKey(CRMFEncryptedKey *inEncrKey)
   1.901 +{
   1.902 +    return crmf_destroy_encrypted_key(inEncrKey, PR_TRUE);
   1.903 +}
   1.904 +
   1.905 +SECStatus
   1.906 +crmf_copy_pkiarchiveoptions(PLArenaPool           *poolp,
   1.907 +			    CRMFPKIArchiveOptions *destOpt,
   1.908 +			    CRMFPKIArchiveOptions *srcOpt)
   1.909 +{
   1.910 +    SECStatus rv;
   1.911 +    destOpt->archOption = srcOpt->archOption;
   1.912 +    switch (srcOpt->archOption) {
   1.913 +    case crmfEncryptedPrivateKey:
   1.914 +        rv = crmf_copy_encryptedkey(poolp,
   1.915 +				    &srcOpt->option.encryptedKey,
   1.916 +				    &destOpt->option.encryptedKey);
   1.917 +        break;
   1.918 +    case crmfKeyGenParameters:
   1.919 +    case crmfArchiveRemGenPrivKey:
   1.920 +        /* We've got a union, so having a pointer to one is just
   1.921 +	 * like having a pointer to the other one.
   1.922 +	 */
   1.923 +        rv = SECITEM_CopyItem(poolp, 
   1.924 +			      &destOpt->option.keyGenParameters,
   1.925 +			      &srcOpt->option.keyGenParameters);
   1.926 +	break;
   1.927 +    default:
   1.928 +        rv = SECFailure;
   1.929 +    }
   1.930 +    return rv;
   1.931 +}
   1.932 +
   1.933 +static SECStatus
   1.934 +crmf_check_and_adjust_archoption(CRMFControl *inControl)
   1.935 +{
   1.936 +    CRMFPKIArchiveOptions *options;
   1.937 +
   1.938 +    options = &inControl->value.archiveOptions;
   1.939 +    if (options->archOption == crmfNoArchiveOptions) {
   1.940 +        /* It hasn't been set, so figure it out from the 
   1.941 +	 * der.
   1.942 +	 */
   1.943 +        switch (inControl->derValue.data[0] & 0x0f) {
   1.944 +	case 0:
   1.945 +	    options->archOption = crmfEncryptedPrivateKey;
   1.946 +	    break;
   1.947 +	case 1:
   1.948 +	    options->archOption = crmfKeyGenParameters;
   1.949 +	    break;
   1.950 +	case 2:
   1.951 +	    options->archOption = crmfArchiveRemGenPrivKey;
   1.952 +	    break;
   1.953 +	default:
   1.954 +	    /* We've got bad DER.  Return an error. */
   1.955 +	    return SECFailure;
   1.956 +	}
   1.957 +    }
   1.958 +    return SECSuccess;
   1.959 +}
   1.960 +
   1.961 +static const SEC_ASN1Template *
   1.962 +crmf_get_pkiarchive_subtemplate(CRMFControl *inControl)
   1.963 +{
   1.964 +    const SEC_ASN1Template *retTemplate;
   1.965 +    SECStatus               rv;
   1.966 +    /*
   1.967 +     * We could be in the process of decoding, in which case the
   1.968 +     * archOption field will not be set.  Let's check it and set 
   1.969 +     * it accordingly.
   1.970 +     */
   1.971 +
   1.972 +    rv = crmf_check_and_adjust_archoption(inControl);
   1.973 +    if (rv != SECSuccess) {
   1.974 +        return NULL;
   1.975 +    }
   1.976 +
   1.977 +    switch (inControl->value.archiveOptions.archOption) {
   1.978 +    case crmfEncryptedPrivateKey:
   1.979 +        retTemplate = CRMFEncryptedKeyWithEncryptedValueTemplate;
   1.980 +	inControl->value.archiveOptions.option.encryptedKey.encKeyChoice =
   1.981 +	  crmfEncryptedValueChoice;
   1.982 +	break;
   1.983 +    default:
   1.984 +        retTemplate = NULL;
   1.985 +    }
   1.986 +    return retTemplate;
   1.987 +}
   1.988 +
   1.989 +const SEC_ASN1Template*
   1.990 +crmf_get_pkiarchiveoptions_subtemplate(CRMFControl *inControl)
   1.991 +{
   1.992 +    const SEC_ASN1Template *retTemplate;
   1.993 +
   1.994 +    switch (inControl->tag) {
   1.995 +    case SEC_OID_PKIX_REGCTRL_REGTOKEN:
   1.996 +    case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
   1.997 +        retTemplate = SEC_ASN1_GET(SEC_UTF8StringTemplate);
   1.998 +	break;
   1.999 +    case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
  1.1000 +        retTemplate = crmf_get_pkiarchive_subtemplate(inControl);
  1.1001 +	break;
  1.1002 +    case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
  1.1003 +    case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
  1.1004 +    case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
  1.1005 +        /* We don't support these controls, so we fail for now.*/
  1.1006 +        retTemplate = NULL;
  1.1007 +	break;
  1.1008 +    default:
  1.1009 +        retTemplate = NULL;
  1.1010 +    }
  1.1011 +    return retTemplate;
  1.1012 +}
  1.1013 +
  1.1014 +static SECStatus
  1.1015 +crmf_encode_pkiarchiveoptions(PLArenaPool *poolp, CRMFControl *inControl)
  1.1016 +{
  1.1017 +    const SEC_ASN1Template *asn1Template;
  1.1018 +
  1.1019 +    asn1Template = crmf_get_pkiarchiveoptions_subtemplate(inControl);
  1.1020 +    /* We've got a union, so passing a pointer to one element of the 
  1.1021 +     * union, is the same as passing a pointer to any of the other
  1.1022 +     * members of the union.
  1.1023 +     */
  1.1024 +    SEC_ASN1EncodeItem(poolp, &inControl->derValue,
  1.1025 +                       &inControl->value.archiveOptions, asn1Template);
  1.1026 +
  1.1027 +    if (inControl->derValue.data == NULL) {
  1.1028 +        goto loser;
  1.1029 +    }
  1.1030 +    return SECSuccess;
  1.1031 + loser:
  1.1032 +    return SECFailure;
  1.1033 +}
  1.1034 +
  1.1035 +SECStatus
  1.1036 +CRMF_CertRequestSetPKIArchiveOptions(CRMFCertRequest       *inCertReq,
  1.1037 +				     CRMFPKIArchiveOptions *inOptions)
  1.1038 +{
  1.1039 +    CRMFControl *newControl;
  1.1040 +    PLArenaPool *poolp;
  1.1041 +    SECStatus    rv;
  1.1042 +    void        *mark;
  1.1043 +    
  1.1044 +    PORT_Assert(inCertReq != NULL && inOptions != NULL);
  1.1045 +    if (inCertReq == NULL || inOptions == NULL) {
  1.1046 +        return SECFailure;
  1.1047 +    }
  1.1048 +    poolp = inCertReq->poolp;
  1.1049 +    mark = PORT_ArenaMark(poolp);
  1.1050 +    rv = crmf_add_new_control(inCertReq, 
  1.1051 +			      SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS,
  1.1052 +			      &newControl);
  1.1053 +    if (rv != SECSuccess) {
  1.1054 +        goto loser;
  1.1055 +    }
  1.1056 +
  1.1057 +    rv = crmf_copy_pkiarchiveoptions(poolp, 
  1.1058 +				     &newControl->value.archiveOptions,
  1.1059 +				     inOptions);
  1.1060 +    if (rv != SECSuccess) {
  1.1061 +        goto loser;
  1.1062 +    }
  1.1063 +
  1.1064 +    rv = crmf_encode_pkiarchiveoptions(poolp, newControl); 
  1.1065 +    if (rv != SECSuccess) {
  1.1066 +        goto loser;
  1.1067 +    }
  1.1068 +    PORT_ArenaUnmark(poolp, mark);
  1.1069 +    return SECSuccess;
  1.1070 + loser:
  1.1071 +    PORT_ArenaRelease(poolp, mark);
  1.1072 +    return SECFailure;
  1.1073 +}
  1.1074 +
  1.1075 +static SECStatus
  1.1076 +crmf_destroy_control(CRMFControl *inControl, PRBool freeit)
  1.1077 +{
  1.1078 +    PORT_Assert(inControl != NULL);
  1.1079 +    if (inControl != NULL) {
  1.1080 +        SECITEM_FreeItem(&inControl->derTag, PR_FALSE);
  1.1081 +        SECITEM_FreeItem(&inControl->derValue, PR_FALSE);
  1.1082 +	/* None of the other tags require special processing at 
  1.1083 +	 * the moment when freeing because they are not supported,
  1.1084 +	 * but if/when they are, add the necessary routines here.  
  1.1085 +	 * If all controls are supported, then every member of the 
  1.1086 +	 * union inControl->value will have a case that deals with 
  1.1087 +	 * it in the following switch statement.
  1.1088 +	 */
  1.1089 +	switch (inControl->tag) {
  1.1090 +	case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
  1.1091 +	    crmf_destroy_pkiarchiveoptions(&inControl->value.archiveOptions,
  1.1092 +					   PR_FALSE);
  1.1093 +	    break;
  1.1094 +        default:
  1.1095 +           /* Put this here to get rid of all those annoying warnings.*/
  1.1096 +           break;
  1.1097 +	}
  1.1098 +	if (freeit) {
  1.1099 +	    PORT_Free(inControl);
  1.1100 +	}
  1.1101 +    }
  1.1102 +    return SECSuccess;
  1.1103 +}
  1.1104 +
  1.1105 +SECStatus
  1.1106 +CRMF_DestroyControl(CRMFControl *inControl)
  1.1107 +{
  1.1108 +    return crmf_destroy_control(inControl, PR_TRUE);
  1.1109 +}
  1.1110 +
  1.1111 +static SECOidTag
  1.1112 +crmf_controltype_to_tag(CRMFControlType inControlType)
  1.1113 +{
  1.1114 +    SECOidTag retVal;
  1.1115 +
  1.1116 +    switch(inControlType) {
  1.1117 +    case crmfRegTokenControl:
  1.1118 +      retVal = SEC_OID_PKIX_REGCTRL_REGTOKEN; 
  1.1119 +      break;
  1.1120 +    case crmfAuthenticatorControl:
  1.1121 +      retVal = SEC_OID_PKIX_REGCTRL_AUTHENTICATOR;
  1.1122 +      break;
  1.1123 +    case crmfPKIPublicationInfoControl:
  1.1124 +      retVal = SEC_OID_PKIX_REGCTRL_PKIPUBINFO;
  1.1125 +      break;
  1.1126 +    case crmfPKIArchiveOptionsControl:
  1.1127 +      retVal = SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS;
  1.1128 +      break;
  1.1129 +    case crmfOldCertIDControl:
  1.1130 +      retVal = SEC_OID_PKIX_REGCTRL_OLD_CERT_ID;
  1.1131 +      break;
  1.1132 +    case crmfProtocolEncrKeyControl:
  1.1133 +      retVal = SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY;
  1.1134 +      break;
  1.1135 +    default:
  1.1136 +      retVal = SEC_OID_UNKNOWN;
  1.1137 +      break;
  1.1138 +    }
  1.1139 +    return retVal;
  1.1140 +}
  1.1141 +
  1.1142 +PRBool
  1.1143 +CRMF_CertRequestIsControlPresent(CRMFCertRequest *inCertReq,
  1.1144 +				 CRMFControlType  inControlType)
  1.1145 +{
  1.1146 +    SECOidTag controlTag;
  1.1147 +    int       i;
  1.1148 +
  1.1149 +    PORT_Assert(inCertReq != NULL);
  1.1150 +    if (inCertReq == NULL || inCertReq->controls == NULL) {
  1.1151 +        return PR_FALSE;
  1.1152 +    }
  1.1153 +    controlTag = crmf_controltype_to_tag(inControlType);
  1.1154 +    for (i=0; inCertReq->controls[i] != NULL; i++) {
  1.1155 +        if (inCertReq->controls[i]->tag == controlTag) {
  1.1156 +	    return PR_TRUE;
  1.1157 +	}
  1.1158 +    }
  1.1159 +    return PR_FALSE;
  1.1160 +}
  1.1161 +

mercurial