security/nss/lib/crmf/crmfpop.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/crmf/crmfpop.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,600 @@
     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 +
    1.10 +#include "crmf.h"
    1.11 +#include "crmfi.h"
    1.12 +#include "secasn1.h"
    1.13 +#include "keyhi.h"
    1.14 +#include "cryptohi.h"
    1.15 +
    1.16 +#define CRMF_DEFAULT_ALLOC_SIZE 1024
    1.17 +
    1.18 +SECStatus
    1.19 +crmf_init_encoder_callback_arg (struct crmfEncoderArg *encoderArg, 
    1.20 +				SECItem               *derDest) 
    1.21 +{
    1.22 +    derDest->data = PORT_ZNewArray(unsigned char, CRMF_DEFAULT_ALLOC_SIZE);
    1.23 +    if (derDest->data == NULL) {
    1.24 +        return SECFailure;
    1.25 +    }
    1.26 +    derDest->len = 0;
    1.27 +    encoderArg->allocatedLen = CRMF_DEFAULT_ALLOC_SIZE;
    1.28 +    encoderArg->buffer = derDest;
    1.29 +    return SECSuccess;
    1.30 +
    1.31 +}
    1.32 +
    1.33 +/* Caller should release or unmark the pool, instead of doing it here.
    1.34 +** But there are NO callers of this function at present...
    1.35 +*/
    1.36 +SECStatus 
    1.37 +CRMF_CertReqMsgSetRAVerifiedPOP(CRMFCertReqMsg *inCertReqMsg)
    1.38 +{
    1.39 +    SECItem               *dummy;
    1.40 +    CRMFProofOfPossession *pop;
    1.41 +    PLArenaPool           *poolp;
    1.42 +    void                  *mark;
    1.43 +
    1.44 +    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
    1.45 +    poolp = inCertReqMsg->poolp;
    1.46 +    mark = PORT_ArenaMark(poolp);
    1.47 +    if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
    1.48 +        return SECFailure;
    1.49 +    }
    1.50 +    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
    1.51 +    if (pop == NULL) {
    1.52 +        goto loser;
    1.53 +    }
    1.54 +    pop->popUsed = crmfRAVerified;
    1.55 +    pop->popChoice.raVerified.data = NULL;
    1.56 +    pop->popChoice.raVerified.len  = 0;
    1.57 +    inCertReqMsg->pop = pop;
    1.58 +    dummy = SEC_ASN1EncodeItem(poolp, &(inCertReqMsg->derPOP),
    1.59 +			       &(pop->popChoice.raVerified),
    1.60 +			       CRMFRAVerifiedTemplate);
    1.61 +    return SECSuccess;
    1.62 + loser:
    1.63 +    PORT_ArenaRelease(poolp, mark);
    1.64 +    return SECFailure;
    1.65 +}
    1.66 +
    1.67 +static SECOidTag
    1.68 +crmf_get_key_sign_tag(SECKEYPublicKey *inPubKey)
    1.69 +{
    1.70 +    /* maintain backward compatibility with older
    1.71 +     * implementations */
    1.72 +    if (inPubKey->keyType == rsaKey) {
    1.73 +        return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
    1.74 +    }
    1.75 +    return SEC_GetSignatureAlgorithmOidTag(inPubKey->keyType, SEC_OID_UNKNOWN);
    1.76 +}
    1.77 +
    1.78 +static SECAlgorithmID*
    1.79 +crmf_create_poposignkey_algid(PLArenaPool      *poolp,
    1.80 +			      SECKEYPublicKey  *inPubKey)
    1.81 +{
    1.82 +    SECAlgorithmID *algID;
    1.83 +    SECOidTag       tag;
    1.84 +    SECStatus       rv;
    1.85 +    void           *mark;
    1.86 +
    1.87 +    mark = PORT_ArenaMark(poolp);
    1.88 +    algID = PORT_ArenaZNew(poolp, SECAlgorithmID);
    1.89 +    if (algID == NULL) {
    1.90 +        goto loser;
    1.91 +    }
    1.92 +    tag = crmf_get_key_sign_tag(inPubKey);
    1.93 +    if (tag == SEC_OID_UNKNOWN) {
    1.94 +        goto loser;
    1.95 +    }
    1.96 +    rv = SECOID_SetAlgorithmID(poolp, algID, tag, NULL);
    1.97 +    if (rv != SECSuccess) {
    1.98 +        goto loser;
    1.99 +    }
   1.100 +    PORT_ArenaUnmark(poolp, mark);
   1.101 +    return algID;
   1.102 + loser:
   1.103 +    PORT_ArenaRelease(poolp, mark);
   1.104 +    return NULL;
   1.105 +}
   1.106 +
   1.107 +static CRMFPOPOSigningKeyInput*
   1.108 +crmf_create_poposigningkeyinput(PLArenaPool *poolp, CERTCertificate *inCert,
   1.109 +				CRMFMACPasswordCallback fn, void *arg)
   1.110 +{
   1.111 +  /* PSM isn't going to do this, so we'll fail here for now.*/
   1.112 +     return NULL;
   1.113 +}
   1.114 +
   1.115 +void
   1.116 +crmf_generic_encoder_callback(void *arg, const char* buf, unsigned long len,
   1.117 +			      int depth, SEC_ASN1EncodingPart data_kind)
   1.118 +{
   1.119 +    struct crmfEncoderArg *encoderArg = (struct crmfEncoderArg*)arg;
   1.120 +    unsigned char *cursor;
   1.121 +    
   1.122 +   if (encoderArg->buffer->len + len > encoderArg->allocatedLen) {
   1.123 +        int newSize = encoderArg->buffer->len+CRMF_DEFAULT_ALLOC_SIZE;
   1.124 +        void *dummy = PORT_Realloc(encoderArg->buffer->data, newSize);
   1.125 +	if (dummy == NULL) {
   1.126 +	    /* I really want to return an error code here */
   1.127 +	    PORT_Assert(0);
   1.128 +	    return;
   1.129 +	}
   1.130 +	encoderArg->buffer->data = dummy;
   1.131 +	encoderArg->allocatedLen = newSize;
   1.132 +    }
   1.133 +    cursor = &(encoderArg->buffer->data[encoderArg->buffer->len]);
   1.134 +    PORT_Memcpy (cursor, buf, len);
   1.135 +    encoderArg->buffer->len += len;    
   1.136 +}
   1.137 +
   1.138 +static SECStatus
   1.139 +crmf_encode_certreq(CRMFCertRequest *inCertReq, SECItem *derDest)
   1.140 +{
   1.141 +    struct crmfEncoderArg encoderArg;
   1.142 +    SECStatus             rv;
   1.143 +  
   1.144 +    rv = crmf_init_encoder_callback_arg (&encoderArg, derDest);
   1.145 +    if (rv != SECSuccess) {
   1.146 +        return SECFailure;
   1.147 +    }
   1.148 +    return SEC_ASN1Encode(inCertReq, CRMFCertRequestTemplate, 
   1.149 +			  crmf_generic_encoder_callback, &encoderArg);
   1.150 +}
   1.151 +
   1.152 +static SECStatus
   1.153 +crmf_sign_certreq(PLArenaPool        *poolp,
   1.154 +		  CRMFPOPOSigningKey *crmfSignKey, 
   1.155 +		  CRMFCertRequest    *certReq,
   1.156 +		  SECKEYPrivateKey   *inKey,
   1.157 +		  SECAlgorithmID     *inAlgId)
   1.158 +{
   1.159 +    SECItem                      derCertReq = { siBuffer, NULL, 0 };
   1.160 +    SECItem                      certReqSig = { siBuffer, NULL, 0 };
   1.161 +    SECStatus                    rv = SECSuccess;
   1.162 +
   1.163 +    rv = crmf_encode_certreq(certReq, &derCertReq);
   1.164 +    if (rv != SECSuccess) {
   1.165 +       goto loser;
   1.166 +    }
   1.167 +    rv = SEC_SignData(&certReqSig, derCertReq.data, derCertReq.len,
   1.168 +		      inKey,SECOID_GetAlgorithmTag(inAlgId));
   1.169 +    if (rv != SECSuccess) {
   1.170 +        goto loser;
   1.171 +    }
   1.172 + 
   1.173 +    /* Now make it a part of the POPOSigningKey */
   1.174 +    rv = SECITEM_CopyItem(poolp, &(crmfSignKey->signature), &certReqSig);
   1.175 +    /* Convert this length to number of bits */
   1.176 +    crmfSignKey->signature.len <<= 3; 
   1.177 +   
   1.178 + loser:
   1.179 +    if (derCertReq.data != NULL) {
   1.180 +        PORT_Free(derCertReq.data);
   1.181 +    }
   1.182 +    if (certReqSig.data != NULL) {
   1.183 +        PORT_Free(certReqSig.data);
   1.184 +    }
   1.185 +    return rv;
   1.186 +}
   1.187 +
   1.188 +static SECStatus
   1.189 +crmf_create_poposignkey(PLArenaPool             *poolp,
   1.190 +			CRMFCertReqMsg          *inCertReqMsg, 
   1.191 +			CRMFPOPOSigningKeyInput *signKeyInput, 
   1.192 +			SECKEYPrivateKey        *inPrivKey,
   1.193 +			SECAlgorithmID          *inAlgID,
   1.194 +			CRMFPOPOSigningKey      *signKey) 
   1.195 +{
   1.196 +    CRMFCertRequest    *certReq;
   1.197 +    void               *mark;
   1.198 +    PRBool              useSignKeyInput;
   1.199 +    SECStatus           rv;
   1.200 +    
   1.201 +    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL);
   1.202 +    mark = PORT_ArenaMark(poolp);
   1.203 +    if (signKey == NULL) {
   1.204 +        goto loser;
   1.205 +    }
   1.206 +    certReq = inCertReqMsg->certReq;
   1.207 +    useSignKeyInput = !(CRMF_DoesRequestHaveField(certReq,crmfSubject)  &&
   1.208 +			CRMF_DoesRequestHaveField(certReq,crmfPublicKey));
   1.209 +
   1.210 +    if (useSignKeyInput) {
   1.211 +        goto loser; 
   1.212 +    } else {
   1.213 +        rv = crmf_sign_certreq(poolp, signKey, certReq,inPrivKey, inAlgID);
   1.214 +	if (rv != SECSuccess) {
   1.215 +	    goto loser;
   1.216 +	}
   1.217 +    }
   1.218 +    PORT_ArenaUnmark(poolp,mark);
   1.219 +    return SECSuccess;
   1.220 + loser:
   1.221 +    PORT_ArenaRelease(poolp,mark);
   1.222 +    return SECFailure;
   1.223 +}
   1.224 +
   1.225 +SECStatus
   1.226 +CRMF_CertReqMsgSetSignaturePOP(CRMFCertReqMsg   *inCertReqMsg,
   1.227 +			       SECKEYPrivateKey *inPrivKey,
   1.228 +			       SECKEYPublicKey  *inPubKey,
   1.229 +			       CERTCertificate  *inCertForInput,
   1.230 +			       CRMFMACPasswordCallback  fn,
   1.231 +			       void                    *arg)
   1.232 +{
   1.233 +    SECAlgorithmID  *algID;
   1.234 +    PLArenaPool     *poolp;
   1.235 +    SECItem          derTemp = {siBuffer, NULL, 0};
   1.236 +    void            *mark;
   1.237 +    SECStatus        rv;
   1.238 +    CRMFPOPOSigningKeyInput *signKeyInput = NULL;
   1.239 +    CRMFCertRequest         *certReq;
   1.240 +    CRMFProofOfPossession   *pop;
   1.241 +    struct crmfEncoderArg    encoderArg;
   1.242 +
   1.243 +    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL &&
   1.244 +		inCertReqMsg->pop == NULL);
   1.245 +    certReq = inCertReqMsg->certReq;
   1.246 +    if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice || 
   1.247 +	!CRMF_DoesRequestHaveField(certReq, crmfPublicKey)) {
   1.248 +        return SECFailure;
   1.249 +    } 
   1.250 +    poolp = inCertReqMsg->poolp;
   1.251 +    mark = PORT_ArenaMark(poolp);
   1.252 +    algID = crmf_create_poposignkey_algid(poolp, inPubKey);
   1.253 +
   1.254 +    if(!CRMF_DoesRequestHaveField(certReq,crmfSubject)) {
   1.255 +        signKeyInput = crmf_create_poposigningkeyinput(poolp, inCertForInput,
   1.256 +						       fn, arg);
   1.257 +	if (signKeyInput == NULL) {
   1.258 +	    goto loser;
   1.259 +	}
   1.260 +    }
   1.261 +
   1.262 +    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
   1.263 +    if (pop == NULL) {
   1.264 +        goto loser;
   1.265 +    }
   1.266 +    
   1.267 +    rv = crmf_create_poposignkey(poolp, inCertReqMsg, 
   1.268 +				 signKeyInput, inPrivKey, algID,
   1.269 +				 &(pop->popChoice.signature));
   1.270 +    if (rv != SECSuccess) {
   1.271 +        goto loser;
   1.272 +    }
   1.273 +
   1.274 +    pop->popUsed = crmfSignature;
   1.275 +    pop->popChoice.signature.algorithmIdentifier = algID;
   1.276 +    inCertReqMsg->pop = pop;
   1.277 +  
   1.278 +    rv = crmf_init_encoder_callback_arg (&encoderArg, &derTemp);
   1.279 +    if (rv != SECSuccess) {
   1.280 +        goto loser;
   1.281 +    }
   1.282 +    rv = SEC_ASN1Encode(&pop->popChoice.signature, 
   1.283 +			CRMFPOPOSigningKeyTemplate,
   1.284 +			crmf_generic_encoder_callback, &encoderArg);
   1.285 +    if (rv != SECSuccess) {
   1.286 +        goto loser;
   1.287 +    }
   1.288 +    rv = SECITEM_CopyItem(poolp, &(inCertReqMsg->derPOP), &derTemp);
   1.289 +    if (rv != SECSuccess) {
   1.290 +        goto loser;
   1.291 +    }
   1.292 +    PORT_Free (derTemp.data);
   1.293 +    PORT_ArenaUnmark(poolp,mark);
   1.294 +    return SECSuccess;
   1.295 +
   1.296 + loser:
   1.297 +    PORT_ArenaRelease(poolp,mark);
   1.298 +    if (derTemp.data != NULL) {
   1.299 +        PORT_Free(derTemp.data);
   1.300 +    }
   1.301 +    return SECFailure;
   1.302 +}
   1.303 +
   1.304 +static const SEC_ASN1Template*
   1.305 +crmf_get_popoprivkey_subtemplate(CRMFPOPOPrivKey *inPrivKey) 
   1.306 +{
   1.307 +    const SEC_ASN1Template *retTemplate = NULL;
   1.308 +
   1.309 +    switch (inPrivKey->messageChoice) {
   1.310 +    case crmfThisMessage:
   1.311 +        retTemplate = CRMFThisMessageTemplate;
   1.312 +	break;
   1.313 +    case crmfSubsequentMessage:
   1.314 +        retTemplate = CRMFSubsequentMessageTemplate;
   1.315 +	break;
   1.316 +    case crmfDHMAC:
   1.317 +        retTemplate = CRMFDHMACTemplate;
   1.318 +	break;
   1.319 +    default:
   1.320 +        retTemplate = NULL;
   1.321 +    }
   1.322 +    return retTemplate;
   1.323 +}
   1.324 +
   1.325 +static SECStatus
   1.326 +crmf_encode_popoprivkey(PLArenaPool            *poolp,
   1.327 +			CRMFCertReqMsg         *inCertReqMsg,
   1.328 +			CRMFPOPOPrivKey        *popoPrivKey,
   1.329 +			const SEC_ASN1Template *privKeyTemplate)
   1.330 +{
   1.331 +    struct crmfEncoderArg   encoderArg;
   1.332 +    SECItem                 derTemp = { siBuffer, NULL, 0 };
   1.333 +    SECStatus               rv;
   1.334 +    void                   *mark;
   1.335 +    const SEC_ASN1Template *subDerTemplate;
   1.336 +
   1.337 +    mark = PORT_ArenaMark(poolp);
   1.338 +    rv = crmf_init_encoder_callback_arg(&encoderArg, &derTemp);
   1.339 +    if (rv != SECSuccess) {
   1.340 +        goto loser;
   1.341 +    }
   1.342 +    subDerTemplate = crmf_get_popoprivkey_subtemplate(popoPrivKey);
   1.343 +    /* We've got a union, so a pointer to one item is a pointer to 
   1.344 +     * all the items in the union.
   1.345 +     */
   1.346 +    rv = SEC_ASN1Encode(&popoPrivKey->message.thisMessage, 
   1.347 +			subDerTemplate,
   1.348 +			crmf_generic_encoder_callback, &encoderArg);
   1.349 +    if (rv != SECSuccess) {
   1.350 +        goto loser;
   1.351 +    }
   1.352 +    if (encoderArg.allocatedLen > derTemp.len+2) {
   1.353 +        void *dummy = PORT_Realloc(derTemp.data, derTemp.len+2);
   1.354 +	if (dummy == NULL) {
   1.355 +	    goto loser;
   1.356 +	}
   1.357 +	derTemp.data = dummy;
   1.358 +    }
   1.359 +    PORT_Memmove(&derTemp.data[2], &derTemp.data[0], derTemp.len);
   1.360 +    /* I couldn't figure out how to get the ASN1 encoder to implicitly
   1.361 +     * tag an implicitly tagged der blob.  So I'm putting in the outter-
   1.362 +     * most tag myself. -javi
   1.363 +     */
   1.364 +    derTemp.data[0] = (unsigned char)privKeyTemplate->kind;
   1.365 +    derTemp.data[1] = (unsigned char)derTemp.len;
   1.366 +    derTemp.len += 2;
   1.367 +    rv = SECITEM_CopyItem(poolp, &inCertReqMsg->derPOP, &derTemp);
   1.368 +    if (rv != SECSuccess) {
   1.369 +        goto loser;
   1.370 +    }
   1.371 +    PORT_Free(derTemp.data);
   1.372 +    PORT_ArenaUnmark(poolp, mark);
   1.373 +    return SECSuccess;
   1.374 + loser:
   1.375 +    PORT_ArenaRelease(poolp, mark);
   1.376 +    if (derTemp.data) {
   1.377 +        PORT_Free(derTemp.data);
   1.378 +    }
   1.379 +    return SECFailure;
   1.380 +}
   1.381 +
   1.382 +static const SEC_ASN1Template*
   1.383 +crmf_get_template_for_privkey(CRMFPOPChoice inChoice) 
   1.384 +{
   1.385 +    switch (inChoice) {
   1.386 +    case crmfKeyAgreement:
   1.387 +        return CRMFPOPOKeyAgreementTemplate;
   1.388 +    case crmfKeyEncipherment:
   1.389 +        return CRMFPOPOKeyEnciphermentTemplate;
   1.390 +    default:
   1.391 +        break;
   1.392 +    }
   1.393 +    return NULL;
   1.394 +}
   1.395 +
   1.396 +static SECStatus
   1.397 +crmf_add_privkey_thismessage(CRMFCertReqMsg *inCertReqMsg, SECItem *encPrivKey,
   1.398 +			     CRMFPOPChoice inChoice)
   1.399 +{
   1.400 +    PLArenaPool           *poolp;
   1.401 +    void                  *mark;
   1.402 +    CRMFPOPOPrivKey       *popoPrivKey;
   1.403 +    CRMFProofOfPossession *pop;
   1.404 +    SECStatus              rv;
   1.405 +
   1.406 +    PORT_Assert(inCertReqMsg != NULL && encPrivKey != NULL);
   1.407 +    poolp = inCertReqMsg->poolp;
   1.408 +    mark = PORT_ArenaMark(poolp);
   1.409 +    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
   1.410 +    if (pop == NULL) {
   1.411 +        goto loser;
   1.412 +    }
   1.413 +    pop->popUsed = inChoice;
   1.414 +    /* popChoice is a union, so getting a pointer to one
   1.415 +     * field gives me a pointer to the other fields as
   1.416 +     * well.  This in essence points to both 
   1.417 +     * pop->popChoice.keyEncipherment and
   1.418 +     * pop->popChoice.keyAgreement
   1.419 +     */
   1.420 +    popoPrivKey = &pop->popChoice.keyEncipherment;
   1.421 +
   1.422 +    rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.thisMessage),
   1.423 +			  encPrivKey);
   1.424 +    if (rv != SECSuccess) {
   1.425 +        goto loser;
   1.426 +    }
   1.427 +    popoPrivKey->message.thisMessage.len <<= 3;
   1.428 +    popoPrivKey->messageChoice = crmfThisMessage;
   1.429 +    inCertReqMsg->pop = pop;
   1.430 +    rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
   1.431 +				 crmf_get_template_for_privkey(inChoice));
   1.432 +    if (rv != SECSuccess) {
   1.433 +        goto loser;
   1.434 +    }
   1.435 +    PORT_ArenaUnmark(poolp, mark);
   1.436 +    return SECSuccess;
   1.437 +    
   1.438 + loser:
   1.439 +    PORT_ArenaRelease(poolp, mark);
   1.440 +    return SECFailure;
   1.441 +}
   1.442 +
   1.443 +static SECStatus
   1.444 +crmf_add_privkey_dhmac(CRMFCertReqMsg *inCertReqMsg, SECItem *dhmac,
   1.445 +                             CRMFPOPChoice inChoice)
   1.446 +{
   1.447 +    PLArenaPool           *poolp;
   1.448 +    void                  *mark;
   1.449 +    CRMFPOPOPrivKey       *popoPrivKey;
   1.450 +    CRMFProofOfPossession *pop;
   1.451 +    SECStatus              rv;
   1.452 +
   1.453 +    PORT_Assert(inCertReqMsg != NULL && dhmac != NULL);
   1.454 +    poolp = inCertReqMsg->poolp;
   1.455 +    mark = PORT_ArenaMark(poolp);
   1.456 +    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
   1.457 +    if (pop == NULL) {
   1.458 +        goto loser;
   1.459 +    }
   1.460 +    pop->popUsed = inChoice;
   1.461 +    popoPrivKey = &pop->popChoice.keyAgreement;
   1.462 +
   1.463 +    rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.dhMAC),
   1.464 +                          dhmac);
   1.465 +    if (rv != SECSuccess) {
   1.466 +        goto loser;
   1.467 +    }
   1.468 +    popoPrivKey->message.dhMAC.len <<= 3;
   1.469 +    popoPrivKey->messageChoice = crmfDHMAC;
   1.470 +    inCertReqMsg->pop = pop;
   1.471 +    rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
   1.472 +                                 crmf_get_template_for_privkey(inChoice));
   1.473 +    if (rv != SECSuccess) {
   1.474 +        goto loser;
   1.475 +    }
   1.476 +    PORT_ArenaUnmark(poolp, mark);
   1.477 +    return SECSuccess;
   1.478 +    
   1.479 + loser:
   1.480 +    PORT_ArenaRelease(poolp, mark);
   1.481 +    return SECFailure;
   1.482 +}
   1.483 +
   1.484 +static SECStatus
   1.485 +crmf_add_privkey_subseqmessage(CRMFCertReqMsg        *inCertReqMsg,
   1.486 +			       CRMFSubseqMessOptions  subsequentMessage,
   1.487 +			       CRMFPOPChoice          inChoice)
   1.488 +{
   1.489 +    void                  *mark;
   1.490 +    PLArenaPool           *poolp;
   1.491 +    CRMFProofOfPossession *pop;
   1.492 +    CRMFPOPOPrivKey       *popoPrivKey;
   1.493 +    SECStatus              rv;
   1.494 +    const SEC_ASN1Template *privKeyTemplate;
   1.495 +
   1.496 +    if (subsequentMessage == crmfNoSubseqMess) {
   1.497 +        return SECFailure;
   1.498 +    }
   1.499 +    poolp = inCertReqMsg->poolp;
   1.500 +    mark = PORT_ArenaMark(poolp);
   1.501 +    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
   1.502 +    if (pop == NULL) {
   1.503 +        goto loser;
   1.504 +    }
   1.505 +
   1.506 +    pop->popUsed = inChoice;
   1.507 +    /* 
   1.508 +     * We have a union, so a pointer to one member of the union
   1.509 +     * is also a member to another member of that same union.
   1.510 +     */
   1.511 +    popoPrivKey = &pop->popChoice.keyEncipherment;
   1.512 +
   1.513 +    switch (subsequentMessage) {
   1.514 +    case crmfEncrCert:
   1.515 +        rv = crmf_encode_integer(poolp, 
   1.516 +				 &(popoPrivKey->message.subsequentMessage),
   1.517 +				 0);
   1.518 +	break;
   1.519 +    case crmfChallengeResp:
   1.520 +        rv = crmf_encode_integer(poolp,
   1.521 +				 &(popoPrivKey->message.subsequentMessage),
   1.522 +				 1);
   1.523 +	break;
   1.524 +    default:
   1.525 +        goto loser;
   1.526 +    }
   1.527 +    if (rv != SECSuccess) {
   1.528 +        goto loser;
   1.529 +    }
   1.530 +    popoPrivKey->messageChoice = crmfSubsequentMessage;
   1.531 +    privKeyTemplate = crmf_get_template_for_privkey(inChoice);
   1.532 +    inCertReqMsg->pop = pop;
   1.533 +    rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
   1.534 +				 privKeyTemplate);
   1.535 +
   1.536 +    if (rv != SECSuccess) {
   1.537 +        goto loser;
   1.538 +    }
   1.539 +    PORT_ArenaUnmark(poolp, mark);
   1.540 +    return SECSuccess;
   1.541 + loser:
   1.542 +    PORT_ArenaRelease(poolp, mark);
   1.543 +    return SECFailure;
   1.544 +}
   1.545 +
   1.546 +SECStatus 
   1.547 +CRMF_CertReqMsgSetKeyEnciphermentPOP(CRMFCertReqMsg        *inCertReqMsg,
   1.548 +				     CRMFPOPOPrivKeyChoice  inKeyChoice,
   1.549 +				     CRMFSubseqMessOptions  subseqMess,
   1.550 +				     SECItem               *encPrivKey)
   1.551 +{
   1.552 +    SECStatus rv;
   1.553 +
   1.554 +    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
   1.555 +    if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
   1.556 +        return SECFailure;
   1.557 +    }
   1.558 +    switch (inKeyChoice) {    
   1.559 +    case crmfThisMessage:
   1.560 +        rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
   1.561 +					  crmfKeyEncipherment);
   1.562 +	break;
   1.563 +    case crmfSubsequentMessage:
   1.564 +        rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess, 
   1.565 +					    crmfKeyEncipherment);
   1.566 +        break;
   1.567 +    case crmfDHMAC:
   1.568 +    default:
   1.569 +        rv = SECFailure;
   1.570 +    }
   1.571 +    return rv;
   1.572 +}
   1.573 +
   1.574 +SECStatus 
   1.575 +CRMF_CertReqMsgSetKeyAgreementPOP (CRMFCertReqMsg        *inCertReqMsg,
   1.576 +				   CRMFPOPOPrivKeyChoice  inKeyChoice,
   1.577 +				   CRMFSubseqMessOptions  subseqMess,
   1.578 +				   SECItem               *encPrivKey)
   1.579 +{
   1.580 +    SECStatus rv;
   1.581 +
   1.582 +    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
   1.583 +    switch (inKeyChoice) {    
   1.584 +    case crmfThisMessage:
   1.585 +        rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
   1.586 +					  crmfKeyAgreement);
   1.587 +	break;
   1.588 +    case crmfSubsequentMessage:
   1.589 +        rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess, 
   1.590 +					    crmfKeyAgreement);
   1.591 +	break;
   1.592 +    case crmfDHMAC:
   1.593 +        /* In this case encPrivKey should be the calculated dhMac
   1.594 +         * as specified in RFC 2511 */
   1.595 +        rv = crmf_add_privkey_dhmac(inCertReqMsg, encPrivKey,
   1.596 +                                    crmfKeyAgreement);
   1.597 +        break;
   1.598 +    default:
   1.599 +        rv = SECFailure;
   1.600 +    }
   1.601 +    return rv;
   1.602 +}
   1.603 +

mercurial