security/nss/lib/crmf/crmfpop.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C; tab-width: 8 -*-*/
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6
michael@0 7 #include "crmf.h"
michael@0 8 #include "crmfi.h"
michael@0 9 #include "secasn1.h"
michael@0 10 #include "keyhi.h"
michael@0 11 #include "cryptohi.h"
michael@0 12
michael@0 13 #define CRMF_DEFAULT_ALLOC_SIZE 1024
michael@0 14
michael@0 15 SECStatus
michael@0 16 crmf_init_encoder_callback_arg (struct crmfEncoderArg *encoderArg,
michael@0 17 SECItem *derDest)
michael@0 18 {
michael@0 19 derDest->data = PORT_ZNewArray(unsigned char, CRMF_DEFAULT_ALLOC_SIZE);
michael@0 20 if (derDest->data == NULL) {
michael@0 21 return SECFailure;
michael@0 22 }
michael@0 23 derDest->len = 0;
michael@0 24 encoderArg->allocatedLen = CRMF_DEFAULT_ALLOC_SIZE;
michael@0 25 encoderArg->buffer = derDest;
michael@0 26 return SECSuccess;
michael@0 27
michael@0 28 }
michael@0 29
michael@0 30 /* Caller should release or unmark the pool, instead of doing it here.
michael@0 31 ** But there are NO callers of this function at present...
michael@0 32 */
michael@0 33 SECStatus
michael@0 34 CRMF_CertReqMsgSetRAVerifiedPOP(CRMFCertReqMsg *inCertReqMsg)
michael@0 35 {
michael@0 36 SECItem *dummy;
michael@0 37 CRMFProofOfPossession *pop;
michael@0 38 PLArenaPool *poolp;
michael@0 39 void *mark;
michael@0 40
michael@0 41 PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
michael@0 42 poolp = inCertReqMsg->poolp;
michael@0 43 mark = PORT_ArenaMark(poolp);
michael@0 44 if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
michael@0 45 return SECFailure;
michael@0 46 }
michael@0 47 pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
michael@0 48 if (pop == NULL) {
michael@0 49 goto loser;
michael@0 50 }
michael@0 51 pop->popUsed = crmfRAVerified;
michael@0 52 pop->popChoice.raVerified.data = NULL;
michael@0 53 pop->popChoice.raVerified.len = 0;
michael@0 54 inCertReqMsg->pop = pop;
michael@0 55 dummy = SEC_ASN1EncodeItem(poolp, &(inCertReqMsg->derPOP),
michael@0 56 &(pop->popChoice.raVerified),
michael@0 57 CRMFRAVerifiedTemplate);
michael@0 58 return SECSuccess;
michael@0 59 loser:
michael@0 60 PORT_ArenaRelease(poolp, mark);
michael@0 61 return SECFailure;
michael@0 62 }
michael@0 63
michael@0 64 static SECOidTag
michael@0 65 crmf_get_key_sign_tag(SECKEYPublicKey *inPubKey)
michael@0 66 {
michael@0 67 /* maintain backward compatibility with older
michael@0 68 * implementations */
michael@0 69 if (inPubKey->keyType == rsaKey) {
michael@0 70 return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
michael@0 71 }
michael@0 72 return SEC_GetSignatureAlgorithmOidTag(inPubKey->keyType, SEC_OID_UNKNOWN);
michael@0 73 }
michael@0 74
michael@0 75 static SECAlgorithmID*
michael@0 76 crmf_create_poposignkey_algid(PLArenaPool *poolp,
michael@0 77 SECKEYPublicKey *inPubKey)
michael@0 78 {
michael@0 79 SECAlgorithmID *algID;
michael@0 80 SECOidTag tag;
michael@0 81 SECStatus rv;
michael@0 82 void *mark;
michael@0 83
michael@0 84 mark = PORT_ArenaMark(poolp);
michael@0 85 algID = PORT_ArenaZNew(poolp, SECAlgorithmID);
michael@0 86 if (algID == NULL) {
michael@0 87 goto loser;
michael@0 88 }
michael@0 89 tag = crmf_get_key_sign_tag(inPubKey);
michael@0 90 if (tag == SEC_OID_UNKNOWN) {
michael@0 91 goto loser;
michael@0 92 }
michael@0 93 rv = SECOID_SetAlgorithmID(poolp, algID, tag, NULL);
michael@0 94 if (rv != SECSuccess) {
michael@0 95 goto loser;
michael@0 96 }
michael@0 97 PORT_ArenaUnmark(poolp, mark);
michael@0 98 return algID;
michael@0 99 loser:
michael@0 100 PORT_ArenaRelease(poolp, mark);
michael@0 101 return NULL;
michael@0 102 }
michael@0 103
michael@0 104 static CRMFPOPOSigningKeyInput*
michael@0 105 crmf_create_poposigningkeyinput(PLArenaPool *poolp, CERTCertificate *inCert,
michael@0 106 CRMFMACPasswordCallback fn, void *arg)
michael@0 107 {
michael@0 108 /* PSM isn't going to do this, so we'll fail here for now.*/
michael@0 109 return NULL;
michael@0 110 }
michael@0 111
michael@0 112 void
michael@0 113 crmf_generic_encoder_callback(void *arg, const char* buf, unsigned long len,
michael@0 114 int depth, SEC_ASN1EncodingPart data_kind)
michael@0 115 {
michael@0 116 struct crmfEncoderArg *encoderArg = (struct crmfEncoderArg*)arg;
michael@0 117 unsigned char *cursor;
michael@0 118
michael@0 119 if (encoderArg->buffer->len + len > encoderArg->allocatedLen) {
michael@0 120 int newSize = encoderArg->buffer->len+CRMF_DEFAULT_ALLOC_SIZE;
michael@0 121 void *dummy = PORT_Realloc(encoderArg->buffer->data, newSize);
michael@0 122 if (dummy == NULL) {
michael@0 123 /* I really want to return an error code here */
michael@0 124 PORT_Assert(0);
michael@0 125 return;
michael@0 126 }
michael@0 127 encoderArg->buffer->data = dummy;
michael@0 128 encoderArg->allocatedLen = newSize;
michael@0 129 }
michael@0 130 cursor = &(encoderArg->buffer->data[encoderArg->buffer->len]);
michael@0 131 PORT_Memcpy (cursor, buf, len);
michael@0 132 encoderArg->buffer->len += len;
michael@0 133 }
michael@0 134
michael@0 135 static SECStatus
michael@0 136 crmf_encode_certreq(CRMFCertRequest *inCertReq, SECItem *derDest)
michael@0 137 {
michael@0 138 struct crmfEncoderArg encoderArg;
michael@0 139 SECStatus rv;
michael@0 140
michael@0 141 rv = crmf_init_encoder_callback_arg (&encoderArg, derDest);
michael@0 142 if (rv != SECSuccess) {
michael@0 143 return SECFailure;
michael@0 144 }
michael@0 145 return SEC_ASN1Encode(inCertReq, CRMFCertRequestTemplate,
michael@0 146 crmf_generic_encoder_callback, &encoderArg);
michael@0 147 }
michael@0 148
michael@0 149 static SECStatus
michael@0 150 crmf_sign_certreq(PLArenaPool *poolp,
michael@0 151 CRMFPOPOSigningKey *crmfSignKey,
michael@0 152 CRMFCertRequest *certReq,
michael@0 153 SECKEYPrivateKey *inKey,
michael@0 154 SECAlgorithmID *inAlgId)
michael@0 155 {
michael@0 156 SECItem derCertReq = { siBuffer, NULL, 0 };
michael@0 157 SECItem certReqSig = { siBuffer, NULL, 0 };
michael@0 158 SECStatus rv = SECSuccess;
michael@0 159
michael@0 160 rv = crmf_encode_certreq(certReq, &derCertReq);
michael@0 161 if (rv != SECSuccess) {
michael@0 162 goto loser;
michael@0 163 }
michael@0 164 rv = SEC_SignData(&certReqSig, derCertReq.data, derCertReq.len,
michael@0 165 inKey,SECOID_GetAlgorithmTag(inAlgId));
michael@0 166 if (rv != SECSuccess) {
michael@0 167 goto loser;
michael@0 168 }
michael@0 169
michael@0 170 /* Now make it a part of the POPOSigningKey */
michael@0 171 rv = SECITEM_CopyItem(poolp, &(crmfSignKey->signature), &certReqSig);
michael@0 172 /* Convert this length to number of bits */
michael@0 173 crmfSignKey->signature.len <<= 3;
michael@0 174
michael@0 175 loser:
michael@0 176 if (derCertReq.data != NULL) {
michael@0 177 PORT_Free(derCertReq.data);
michael@0 178 }
michael@0 179 if (certReqSig.data != NULL) {
michael@0 180 PORT_Free(certReqSig.data);
michael@0 181 }
michael@0 182 return rv;
michael@0 183 }
michael@0 184
michael@0 185 static SECStatus
michael@0 186 crmf_create_poposignkey(PLArenaPool *poolp,
michael@0 187 CRMFCertReqMsg *inCertReqMsg,
michael@0 188 CRMFPOPOSigningKeyInput *signKeyInput,
michael@0 189 SECKEYPrivateKey *inPrivKey,
michael@0 190 SECAlgorithmID *inAlgID,
michael@0 191 CRMFPOPOSigningKey *signKey)
michael@0 192 {
michael@0 193 CRMFCertRequest *certReq;
michael@0 194 void *mark;
michael@0 195 PRBool useSignKeyInput;
michael@0 196 SECStatus rv;
michael@0 197
michael@0 198 PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL);
michael@0 199 mark = PORT_ArenaMark(poolp);
michael@0 200 if (signKey == NULL) {
michael@0 201 goto loser;
michael@0 202 }
michael@0 203 certReq = inCertReqMsg->certReq;
michael@0 204 useSignKeyInput = !(CRMF_DoesRequestHaveField(certReq,crmfSubject) &&
michael@0 205 CRMF_DoesRequestHaveField(certReq,crmfPublicKey));
michael@0 206
michael@0 207 if (useSignKeyInput) {
michael@0 208 goto loser;
michael@0 209 } else {
michael@0 210 rv = crmf_sign_certreq(poolp, signKey, certReq,inPrivKey, inAlgID);
michael@0 211 if (rv != SECSuccess) {
michael@0 212 goto loser;
michael@0 213 }
michael@0 214 }
michael@0 215 PORT_ArenaUnmark(poolp,mark);
michael@0 216 return SECSuccess;
michael@0 217 loser:
michael@0 218 PORT_ArenaRelease(poolp,mark);
michael@0 219 return SECFailure;
michael@0 220 }
michael@0 221
michael@0 222 SECStatus
michael@0 223 CRMF_CertReqMsgSetSignaturePOP(CRMFCertReqMsg *inCertReqMsg,
michael@0 224 SECKEYPrivateKey *inPrivKey,
michael@0 225 SECKEYPublicKey *inPubKey,
michael@0 226 CERTCertificate *inCertForInput,
michael@0 227 CRMFMACPasswordCallback fn,
michael@0 228 void *arg)
michael@0 229 {
michael@0 230 SECAlgorithmID *algID;
michael@0 231 PLArenaPool *poolp;
michael@0 232 SECItem derTemp = {siBuffer, NULL, 0};
michael@0 233 void *mark;
michael@0 234 SECStatus rv;
michael@0 235 CRMFPOPOSigningKeyInput *signKeyInput = NULL;
michael@0 236 CRMFCertRequest *certReq;
michael@0 237 CRMFProofOfPossession *pop;
michael@0 238 struct crmfEncoderArg encoderArg;
michael@0 239
michael@0 240 PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL &&
michael@0 241 inCertReqMsg->pop == NULL);
michael@0 242 certReq = inCertReqMsg->certReq;
michael@0 243 if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice ||
michael@0 244 !CRMF_DoesRequestHaveField(certReq, crmfPublicKey)) {
michael@0 245 return SECFailure;
michael@0 246 }
michael@0 247 poolp = inCertReqMsg->poolp;
michael@0 248 mark = PORT_ArenaMark(poolp);
michael@0 249 algID = crmf_create_poposignkey_algid(poolp, inPubKey);
michael@0 250
michael@0 251 if(!CRMF_DoesRequestHaveField(certReq,crmfSubject)) {
michael@0 252 signKeyInput = crmf_create_poposigningkeyinput(poolp, inCertForInput,
michael@0 253 fn, arg);
michael@0 254 if (signKeyInput == NULL) {
michael@0 255 goto loser;
michael@0 256 }
michael@0 257 }
michael@0 258
michael@0 259 pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
michael@0 260 if (pop == NULL) {
michael@0 261 goto loser;
michael@0 262 }
michael@0 263
michael@0 264 rv = crmf_create_poposignkey(poolp, inCertReqMsg,
michael@0 265 signKeyInput, inPrivKey, algID,
michael@0 266 &(pop->popChoice.signature));
michael@0 267 if (rv != SECSuccess) {
michael@0 268 goto loser;
michael@0 269 }
michael@0 270
michael@0 271 pop->popUsed = crmfSignature;
michael@0 272 pop->popChoice.signature.algorithmIdentifier = algID;
michael@0 273 inCertReqMsg->pop = pop;
michael@0 274
michael@0 275 rv = crmf_init_encoder_callback_arg (&encoderArg, &derTemp);
michael@0 276 if (rv != SECSuccess) {
michael@0 277 goto loser;
michael@0 278 }
michael@0 279 rv = SEC_ASN1Encode(&pop->popChoice.signature,
michael@0 280 CRMFPOPOSigningKeyTemplate,
michael@0 281 crmf_generic_encoder_callback, &encoderArg);
michael@0 282 if (rv != SECSuccess) {
michael@0 283 goto loser;
michael@0 284 }
michael@0 285 rv = SECITEM_CopyItem(poolp, &(inCertReqMsg->derPOP), &derTemp);
michael@0 286 if (rv != SECSuccess) {
michael@0 287 goto loser;
michael@0 288 }
michael@0 289 PORT_Free (derTemp.data);
michael@0 290 PORT_ArenaUnmark(poolp,mark);
michael@0 291 return SECSuccess;
michael@0 292
michael@0 293 loser:
michael@0 294 PORT_ArenaRelease(poolp,mark);
michael@0 295 if (derTemp.data != NULL) {
michael@0 296 PORT_Free(derTemp.data);
michael@0 297 }
michael@0 298 return SECFailure;
michael@0 299 }
michael@0 300
michael@0 301 static const SEC_ASN1Template*
michael@0 302 crmf_get_popoprivkey_subtemplate(CRMFPOPOPrivKey *inPrivKey)
michael@0 303 {
michael@0 304 const SEC_ASN1Template *retTemplate = NULL;
michael@0 305
michael@0 306 switch (inPrivKey->messageChoice) {
michael@0 307 case crmfThisMessage:
michael@0 308 retTemplate = CRMFThisMessageTemplate;
michael@0 309 break;
michael@0 310 case crmfSubsequentMessage:
michael@0 311 retTemplate = CRMFSubsequentMessageTemplate;
michael@0 312 break;
michael@0 313 case crmfDHMAC:
michael@0 314 retTemplate = CRMFDHMACTemplate;
michael@0 315 break;
michael@0 316 default:
michael@0 317 retTemplate = NULL;
michael@0 318 }
michael@0 319 return retTemplate;
michael@0 320 }
michael@0 321
michael@0 322 static SECStatus
michael@0 323 crmf_encode_popoprivkey(PLArenaPool *poolp,
michael@0 324 CRMFCertReqMsg *inCertReqMsg,
michael@0 325 CRMFPOPOPrivKey *popoPrivKey,
michael@0 326 const SEC_ASN1Template *privKeyTemplate)
michael@0 327 {
michael@0 328 struct crmfEncoderArg encoderArg;
michael@0 329 SECItem derTemp = { siBuffer, NULL, 0 };
michael@0 330 SECStatus rv;
michael@0 331 void *mark;
michael@0 332 const SEC_ASN1Template *subDerTemplate;
michael@0 333
michael@0 334 mark = PORT_ArenaMark(poolp);
michael@0 335 rv = crmf_init_encoder_callback_arg(&encoderArg, &derTemp);
michael@0 336 if (rv != SECSuccess) {
michael@0 337 goto loser;
michael@0 338 }
michael@0 339 subDerTemplate = crmf_get_popoprivkey_subtemplate(popoPrivKey);
michael@0 340 /* We've got a union, so a pointer to one item is a pointer to
michael@0 341 * all the items in the union.
michael@0 342 */
michael@0 343 rv = SEC_ASN1Encode(&popoPrivKey->message.thisMessage,
michael@0 344 subDerTemplate,
michael@0 345 crmf_generic_encoder_callback, &encoderArg);
michael@0 346 if (rv != SECSuccess) {
michael@0 347 goto loser;
michael@0 348 }
michael@0 349 if (encoderArg.allocatedLen > derTemp.len+2) {
michael@0 350 void *dummy = PORT_Realloc(derTemp.data, derTemp.len+2);
michael@0 351 if (dummy == NULL) {
michael@0 352 goto loser;
michael@0 353 }
michael@0 354 derTemp.data = dummy;
michael@0 355 }
michael@0 356 PORT_Memmove(&derTemp.data[2], &derTemp.data[0], derTemp.len);
michael@0 357 /* I couldn't figure out how to get the ASN1 encoder to implicitly
michael@0 358 * tag an implicitly tagged der blob. So I'm putting in the outter-
michael@0 359 * most tag myself. -javi
michael@0 360 */
michael@0 361 derTemp.data[0] = (unsigned char)privKeyTemplate->kind;
michael@0 362 derTemp.data[1] = (unsigned char)derTemp.len;
michael@0 363 derTemp.len += 2;
michael@0 364 rv = SECITEM_CopyItem(poolp, &inCertReqMsg->derPOP, &derTemp);
michael@0 365 if (rv != SECSuccess) {
michael@0 366 goto loser;
michael@0 367 }
michael@0 368 PORT_Free(derTemp.data);
michael@0 369 PORT_ArenaUnmark(poolp, mark);
michael@0 370 return SECSuccess;
michael@0 371 loser:
michael@0 372 PORT_ArenaRelease(poolp, mark);
michael@0 373 if (derTemp.data) {
michael@0 374 PORT_Free(derTemp.data);
michael@0 375 }
michael@0 376 return SECFailure;
michael@0 377 }
michael@0 378
michael@0 379 static const SEC_ASN1Template*
michael@0 380 crmf_get_template_for_privkey(CRMFPOPChoice inChoice)
michael@0 381 {
michael@0 382 switch (inChoice) {
michael@0 383 case crmfKeyAgreement:
michael@0 384 return CRMFPOPOKeyAgreementTemplate;
michael@0 385 case crmfKeyEncipherment:
michael@0 386 return CRMFPOPOKeyEnciphermentTemplate;
michael@0 387 default:
michael@0 388 break;
michael@0 389 }
michael@0 390 return NULL;
michael@0 391 }
michael@0 392
michael@0 393 static SECStatus
michael@0 394 crmf_add_privkey_thismessage(CRMFCertReqMsg *inCertReqMsg, SECItem *encPrivKey,
michael@0 395 CRMFPOPChoice inChoice)
michael@0 396 {
michael@0 397 PLArenaPool *poolp;
michael@0 398 void *mark;
michael@0 399 CRMFPOPOPrivKey *popoPrivKey;
michael@0 400 CRMFProofOfPossession *pop;
michael@0 401 SECStatus rv;
michael@0 402
michael@0 403 PORT_Assert(inCertReqMsg != NULL && encPrivKey != NULL);
michael@0 404 poolp = inCertReqMsg->poolp;
michael@0 405 mark = PORT_ArenaMark(poolp);
michael@0 406 pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
michael@0 407 if (pop == NULL) {
michael@0 408 goto loser;
michael@0 409 }
michael@0 410 pop->popUsed = inChoice;
michael@0 411 /* popChoice is a union, so getting a pointer to one
michael@0 412 * field gives me a pointer to the other fields as
michael@0 413 * well. This in essence points to both
michael@0 414 * pop->popChoice.keyEncipherment and
michael@0 415 * pop->popChoice.keyAgreement
michael@0 416 */
michael@0 417 popoPrivKey = &pop->popChoice.keyEncipherment;
michael@0 418
michael@0 419 rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.thisMessage),
michael@0 420 encPrivKey);
michael@0 421 if (rv != SECSuccess) {
michael@0 422 goto loser;
michael@0 423 }
michael@0 424 popoPrivKey->message.thisMessage.len <<= 3;
michael@0 425 popoPrivKey->messageChoice = crmfThisMessage;
michael@0 426 inCertReqMsg->pop = pop;
michael@0 427 rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
michael@0 428 crmf_get_template_for_privkey(inChoice));
michael@0 429 if (rv != SECSuccess) {
michael@0 430 goto loser;
michael@0 431 }
michael@0 432 PORT_ArenaUnmark(poolp, mark);
michael@0 433 return SECSuccess;
michael@0 434
michael@0 435 loser:
michael@0 436 PORT_ArenaRelease(poolp, mark);
michael@0 437 return SECFailure;
michael@0 438 }
michael@0 439
michael@0 440 static SECStatus
michael@0 441 crmf_add_privkey_dhmac(CRMFCertReqMsg *inCertReqMsg, SECItem *dhmac,
michael@0 442 CRMFPOPChoice inChoice)
michael@0 443 {
michael@0 444 PLArenaPool *poolp;
michael@0 445 void *mark;
michael@0 446 CRMFPOPOPrivKey *popoPrivKey;
michael@0 447 CRMFProofOfPossession *pop;
michael@0 448 SECStatus rv;
michael@0 449
michael@0 450 PORT_Assert(inCertReqMsg != NULL && dhmac != NULL);
michael@0 451 poolp = inCertReqMsg->poolp;
michael@0 452 mark = PORT_ArenaMark(poolp);
michael@0 453 pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
michael@0 454 if (pop == NULL) {
michael@0 455 goto loser;
michael@0 456 }
michael@0 457 pop->popUsed = inChoice;
michael@0 458 popoPrivKey = &pop->popChoice.keyAgreement;
michael@0 459
michael@0 460 rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.dhMAC),
michael@0 461 dhmac);
michael@0 462 if (rv != SECSuccess) {
michael@0 463 goto loser;
michael@0 464 }
michael@0 465 popoPrivKey->message.dhMAC.len <<= 3;
michael@0 466 popoPrivKey->messageChoice = crmfDHMAC;
michael@0 467 inCertReqMsg->pop = pop;
michael@0 468 rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
michael@0 469 crmf_get_template_for_privkey(inChoice));
michael@0 470 if (rv != SECSuccess) {
michael@0 471 goto loser;
michael@0 472 }
michael@0 473 PORT_ArenaUnmark(poolp, mark);
michael@0 474 return SECSuccess;
michael@0 475
michael@0 476 loser:
michael@0 477 PORT_ArenaRelease(poolp, mark);
michael@0 478 return SECFailure;
michael@0 479 }
michael@0 480
michael@0 481 static SECStatus
michael@0 482 crmf_add_privkey_subseqmessage(CRMFCertReqMsg *inCertReqMsg,
michael@0 483 CRMFSubseqMessOptions subsequentMessage,
michael@0 484 CRMFPOPChoice inChoice)
michael@0 485 {
michael@0 486 void *mark;
michael@0 487 PLArenaPool *poolp;
michael@0 488 CRMFProofOfPossession *pop;
michael@0 489 CRMFPOPOPrivKey *popoPrivKey;
michael@0 490 SECStatus rv;
michael@0 491 const SEC_ASN1Template *privKeyTemplate;
michael@0 492
michael@0 493 if (subsequentMessage == crmfNoSubseqMess) {
michael@0 494 return SECFailure;
michael@0 495 }
michael@0 496 poolp = inCertReqMsg->poolp;
michael@0 497 mark = PORT_ArenaMark(poolp);
michael@0 498 pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
michael@0 499 if (pop == NULL) {
michael@0 500 goto loser;
michael@0 501 }
michael@0 502
michael@0 503 pop->popUsed = inChoice;
michael@0 504 /*
michael@0 505 * We have a union, so a pointer to one member of the union
michael@0 506 * is also a member to another member of that same union.
michael@0 507 */
michael@0 508 popoPrivKey = &pop->popChoice.keyEncipherment;
michael@0 509
michael@0 510 switch (subsequentMessage) {
michael@0 511 case crmfEncrCert:
michael@0 512 rv = crmf_encode_integer(poolp,
michael@0 513 &(popoPrivKey->message.subsequentMessage),
michael@0 514 0);
michael@0 515 break;
michael@0 516 case crmfChallengeResp:
michael@0 517 rv = crmf_encode_integer(poolp,
michael@0 518 &(popoPrivKey->message.subsequentMessage),
michael@0 519 1);
michael@0 520 break;
michael@0 521 default:
michael@0 522 goto loser;
michael@0 523 }
michael@0 524 if (rv != SECSuccess) {
michael@0 525 goto loser;
michael@0 526 }
michael@0 527 popoPrivKey->messageChoice = crmfSubsequentMessage;
michael@0 528 privKeyTemplate = crmf_get_template_for_privkey(inChoice);
michael@0 529 inCertReqMsg->pop = pop;
michael@0 530 rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
michael@0 531 privKeyTemplate);
michael@0 532
michael@0 533 if (rv != SECSuccess) {
michael@0 534 goto loser;
michael@0 535 }
michael@0 536 PORT_ArenaUnmark(poolp, mark);
michael@0 537 return SECSuccess;
michael@0 538 loser:
michael@0 539 PORT_ArenaRelease(poolp, mark);
michael@0 540 return SECFailure;
michael@0 541 }
michael@0 542
michael@0 543 SECStatus
michael@0 544 CRMF_CertReqMsgSetKeyEnciphermentPOP(CRMFCertReqMsg *inCertReqMsg,
michael@0 545 CRMFPOPOPrivKeyChoice inKeyChoice,
michael@0 546 CRMFSubseqMessOptions subseqMess,
michael@0 547 SECItem *encPrivKey)
michael@0 548 {
michael@0 549 SECStatus rv;
michael@0 550
michael@0 551 PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
michael@0 552 if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
michael@0 553 return SECFailure;
michael@0 554 }
michael@0 555 switch (inKeyChoice) {
michael@0 556 case crmfThisMessage:
michael@0 557 rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
michael@0 558 crmfKeyEncipherment);
michael@0 559 break;
michael@0 560 case crmfSubsequentMessage:
michael@0 561 rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess,
michael@0 562 crmfKeyEncipherment);
michael@0 563 break;
michael@0 564 case crmfDHMAC:
michael@0 565 default:
michael@0 566 rv = SECFailure;
michael@0 567 }
michael@0 568 return rv;
michael@0 569 }
michael@0 570
michael@0 571 SECStatus
michael@0 572 CRMF_CertReqMsgSetKeyAgreementPOP (CRMFCertReqMsg *inCertReqMsg,
michael@0 573 CRMFPOPOPrivKeyChoice inKeyChoice,
michael@0 574 CRMFSubseqMessOptions subseqMess,
michael@0 575 SECItem *encPrivKey)
michael@0 576 {
michael@0 577 SECStatus rv;
michael@0 578
michael@0 579 PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
michael@0 580 switch (inKeyChoice) {
michael@0 581 case crmfThisMessage:
michael@0 582 rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
michael@0 583 crmfKeyAgreement);
michael@0 584 break;
michael@0 585 case crmfSubsequentMessage:
michael@0 586 rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess,
michael@0 587 crmfKeyAgreement);
michael@0 588 break;
michael@0 589 case crmfDHMAC:
michael@0 590 /* In this case encPrivKey should be the calculated dhMac
michael@0 591 * as specified in RFC 2511 */
michael@0 592 rv = crmf_add_privkey_dhmac(inCertReqMsg, encPrivKey,
michael@0 593 crmfKeyAgreement);
michael@0 594 break;
michael@0 595 default:
michael@0 596 rv = SECFailure;
michael@0 597 }
michael@0 598 return rv;
michael@0 599 }
michael@0 600

mercurial