security/nss/lib/crmf/crmfcont.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial