1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/crmftest/testcrmf.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1679 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * This program does 5 separate functions. By default, it does them all. 1.10 + * It can be told to do any subset of them. 1.11 + * It does them in this order: 1.12 + * 1.13 + * 1. Generate file of CRMF cert requests. 1.14 + * Generates 2 keys pairs, one for signing, one for encryption. 1.15 + * Can generate RSA or DSA (XXX - DSA is only useful for signing). 1.16 + * Generate a cert request for each of the two public keys. 1.17 + * Generate a single CRMF cert request message that requests both certs. 1.18 + * Leave the generated CRMF request message in file 1.19 + * configdir/CertReqMessages.der 1.20 + * 1.21 + * 2. Decode CRMF Request(s) Message. 1.22 + * Reads in the file configdir/CertReqMessages.der 1.23 + * (either generated by step 1 above, or user supplied). 1.24 + * Decodes it. NOTHING MORE. Drops these decoded results on the floor. 1.25 + * The CMMF response (below) contains a completely unrelated cert. :-( 1.26 + * 1.27 + * 3. CMMF "Stuff". 1.28 + * a) Generates a CMMF response, containing a single cert chain, as if 1.29 + * it was a response to a received CRMF request. But the cert is 1.30 + * simply a user cert from the user's local soft token, whose 1.31 + * nickname is given in the -p option. The CMMF response has no 1.32 + * relationship to the request generated above. The CMMF message 1.33 + * is placed in configdir/CertRepContent.der. 1.34 + * b) Decodes the newly generated CMMF response found in file 1.35 + * configdir/CertRepContent.der and discards the result. 8-/ 1.36 + * c) Generate a CMMF Key Escrow message 1.37 + * needs 2 nicknames: 1.38 + * It takes the public and private keys for the cert identified 1.39 + * by -p nickname, and wraps them with a sym key that is in turn 1.40 + * wrapped with the pubkey in the CA cert, whose nickname is 1.41 + * given with the -s option. 1.42 + * Store the message in configdir/KeyRecRepContent.der 1.43 + * d) Decode the CMMF Key Escrow message generated just above. 1.44 + * Get it from file configdir/KeyRecRepContent.der 1.45 + * This is just a decoder test. Results are discarded. 1.46 + * 1.47 + * 4. Key Recovery 1.48 + * This code does not yet compile, and what it was intended to do 1.49 + * has not been fully determined. 1.50 + * 1.51 + * 5. Challenge/Response. 1.52 + * Haven't analyzed this code yet. 1.53 + * 1.54 + * 1.55 + */ 1.56 + 1.57 +/* KNOWN BUGS: 1.58 +** 1. generates BOTH signing and encryption cert requests, even for DSA keys. 1.59 +** 1.60 +** 2. Does not verify the siganture in the "Proof of Posession" in the 1.61 +** decoded cert requests. It only checks syntax of the POP. 1.62 +** 3. CMMF "Stuff" should be broken up into separate steps, each of 1.63 +** which may be optionally selected. 1.64 +*/ 1.65 + 1.66 +#include <stdio.h> 1.67 +#include "nspr.h" 1.68 +#include "nss.h" 1.69 +#include "crmf.h" 1.70 +#include "secerr.h" 1.71 +#include "pk11func.h" 1.72 +#include "key.h" 1.73 +#include "cmmf.h" 1.74 +#include "plgetopt.h" 1.75 +#include "secutil.h" 1.76 +#include "pk11pqg.h" 1.77 + 1.78 +#if 0 1.79 +#include "pkcs11.h" 1.80 +#include "secmod.h" 1.81 +#include "secmodi.h" 1.82 +#include "pqggen.h" 1.83 +#include "secmod.h" 1.84 +#include "secmodi.h" 1.85 +#include "pkcs11.h" 1.86 +#include "secitem.h" 1.87 +#include "secasn1.h" 1.88 +#include "sechash.h" 1.89 +#endif 1.90 + 1.91 +#define MAX_KEY_LEN 512 1.92 +#define PATH_LEN 150 1.93 +#define BUFF_SIZE 150 1.94 +#define UID_BITS 800 1.95 +#define BPB 8 1.96 +#define CRMF_FILE "CertReqMessages.der" 1.97 + 1.98 +PRTime notBefore; 1.99 +char *personalCert = NULL; 1.100 +char *recoveryEncrypter = NULL; 1.101 +char *caCertName = NULL; 1.102 +static secuPWData pwdata = { PW_NONE, 0 }; 1.103 +char *configdir; 1.104 +PRBool doingDSA = PR_FALSE; 1.105 + 1.106 +CERTCertDBHandle *db; 1.107 + 1.108 +typedef struct { 1.109 + SECKEYPrivateKey *privKey; 1.110 + SECKEYPublicKey *pubKey; 1.111 + CRMFCertRequest *certReq; 1.112 + CRMFCertReqMsg *certReqMsg; 1.113 +} TESTKeyPair; 1.114 + 1.115 +void 1.116 +debug_test(SECItem *src, char *filePath) 1.117 +{ 1.118 + PRFileDesc *fileDesc; 1.119 + 1.120 + fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 1.121 + 0666); 1.122 + if (fileDesc == NULL) { 1.123 + printf ("Could not cretae file %s.\n", filePath); 1.124 + return; 1.125 + } 1.126 + PR_Write(fileDesc, src->data, src->len); 1.127 + 1.128 +} 1.129 + 1.130 +SECStatus 1.131 +get_serial_number(long *dest) 1.132 +{ 1.133 + SECStatus rv; 1.134 + 1.135 + if (dest == NULL) { 1.136 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.137 + return SECFailure; 1.138 + } 1.139 + rv = PK11_GenerateRandom((unsigned char *)dest, sizeof(long)); 1.140 + /* make serial number positive */ 1.141 + if (*dest < 0L) 1.142 + *dest = - *dest; 1.143 + return SECSuccess; 1.144 +} 1.145 + 1.146 +PK11RSAGenParams * 1.147 +GetRSAParams(void) 1.148 +{ 1.149 + PK11RSAGenParams *rsaParams; 1.150 + 1.151 + rsaParams = PORT_ZNew(PK11RSAGenParams); 1.152 + 1.153 + if (rsaParams == NULL) 1.154 + return NULL; 1.155 + 1.156 + rsaParams->keySizeInBits = MAX_KEY_LEN; 1.157 + rsaParams->pe = 0x10001; 1.158 + 1.159 + return rsaParams; 1.160 + 1.161 +} 1.162 + 1.163 +PQGParams* 1.164 +GetDSAParams(void) 1.165 +{ 1.166 + PQGParams *params = NULL; 1.167 + PQGVerify *vfy = NULL; 1.168 + 1.169 + SECStatus rv; 1.170 + 1.171 + rv = PK11_PQG_ParamGen(0, ¶ms, &vfy); 1.172 + if (rv != SECSuccess) { 1.173 + return NULL; 1.174 + } 1.175 + PK11_PQG_DestroyVerify(vfy); 1.176 + return params; 1.177 +} 1.178 + 1.179 +/* Generate a key pair, and then generate a subjectPublicKeyInfo 1.180 +** for the public key in that pair. return all 3. 1.181 +*/ 1.182 +CERTSubjectPublicKeyInfo * 1.183 +GetSubjectPubKeyInfo(TESTKeyPair *pair) 1.184 +{ 1.185 + CERTSubjectPublicKeyInfo *spki = NULL; 1.186 + SECKEYPrivateKey *privKey = NULL; 1.187 + SECKEYPublicKey *pubKey = NULL; 1.188 + PK11SlotInfo *keySlot = NULL; 1.189 + 1.190 + keySlot = PK11_GetInternalKeySlot(); 1.191 + PK11_Authenticate(keySlot, PR_FALSE, &pwdata); 1.192 + 1.193 + 1.194 + if (!doingDSA) { 1.195 + PK11RSAGenParams *rsaParams = GetRSAParams(); 1.196 + if (rsaParams == NULL) { 1.197 + PK11_FreeSlot(keySlot); 1.198 + return NULL; 1.199 + } 1.200 + privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN, 1.201 + (void*)rsaParams, &pubKey, PR_FALSE, 1.202 + PR_FALSE, &pwdata); 1.203 + } else { 1.204 + PQGParams *dsaParams = GetDSAParams(); 1.205 + if (dsaParams == NULL) { 1.206 + PK11_FreeSlot(keySlot); 1.207 + return NULL; 1.208 + } 1.209 + privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN, 1.210 + (void*)dsaParams, &pubKey, PR_FALSE, 1.211 + PR_FALSE, &pwdata); 1.212 + } 1.213 + PK11_FreeSlot(keySlot); 1.214 + if (privKey == NULL || pubKey == NULL) { 1.215 + if (pubKey) { 1.216 + SECKEY_DestroyPublicKey(pubKey); 1.217 + } 1.218 + if (privKey) { 1.219 + SECKEY_DestroyPrivateKey(privKey); 1.220 + } 1.221 + return NULL; 1.222 + } 1.223 + 1.224 + spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey); 1.225 + pair->privKey = privKey; 1.226 + pair->pubKey = pubKey; 1.227 + return spki; 1.228 +} 1.229 + 1.230 + 1.231 +SECStatus 1.232 +InitPKCS11(void) 1.233 +{ 1.234 + PK11SlotInfo *keySlot; 1.235 + 1.236 + PK11_SetPasswordFunc(SECU_GetModulePassword); 1.237 + 1.238 + keySlot = PK11_GetInternalKeySlot(); 1.239 + 1.240 + if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) { 1.241 + if (SECU_ChangePW(keySlot, NULL, NULL) != SECSuccess) { 1.242 + printf ("Initializing the PINs failed.\n"); 1.243 + return SECFailure; 1.244 + } 1.245 + } 1.246 + 1.247 + PK11_FreeSlot(keySlot); 1.248 + return SECSuccess; 1.249 +} 1.250 + 1.251 + 1.252 +void 1.253 +WriteItOut (void *arg, const char *buf, unsigned long len) 1.254 +{ 1.255 + PRFileDesc *fileDesc = (PRFileDesc*)arg; 1.256 + 1.257 + PR_Write(fileDesc, (void*)buf, len); 1.258 +} 1.259 + 1.260 + 1.261 + 1.262 +CRMFCertExtCreationInfo* 1.263 +GetExtensions(void) 1.264 +{ 1.265 + unsigned char keyUsage[4] = { 0x03, 0x02, 0x07, KU_DIGITAL_SIGNATURE }; 1.266 + /* What are these magic numbers? */ 1.267 + SECItem data = { 0, NULL, 0 }; 1.268 + CRMFCertExtension *extension; 1.269 + CRMFCertExtCreationInfo *extInfo = 1.270 + PORT_ZNew(CRMFCertExtCreationInfo); 1.271 + 1.272 + data.data = keyUsage; 1.273 + data.len = sizeof keyUsage; 1.274 + 1.275 + 1.276 + extension = 1.277 + CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, PR_FALSE, &data); 1.278 + if (extension && extInfo) { 1.279 + extInfo->numExtensions = 1; 1.280 + extInfo->extensions = PORT_ZNewArray(CRMFCertExtension*, 1); 1.281 + extInfo->extensions[0] = extension; 1.282 + } 1.283 + return extInfo; 1.284 +} 1.285 + 1.286 +void 1.287 +FreeExtInfo(CRMFCertExtCreationInfo *extInfo) 1.288 +{ 1.289 + int i; 1.290 + 1.291 + for (i=0; i<extInfo->numExtensions; i++) { 1.292 + CRMF_DestroyCertExtension(extInfo->extensions[i]); 1.293 + } 1.294 + PORT_Free(extInfo->extensions); 1.295 + PORT_Free(extInfo); 1.296 +} 1.297 + 1.298 +int 1.299 +InjectCertName( CRMFCertRequest * certReq, 1.300 + CRMFCertTemplateField inTemplateField, 1.301 + const char * inNameString) 1.302 +{ 1.303 + char * nameStr; 1.304 + CERTName * name; 1.305 + int irv = 0; 1.306 + 1.307 + nameStr = PORT_Strdup(inNameString); 1.308 + if (!nameStr) 1.309 + return 5; 1.310 + name = CERT_AsciiToName(nameStr); 1.311 + if (name == NULL) { 1.312 + printf ("Could not create CERTName structure from %s.\n", nameStr); 1.313 + irv = 5; 1.314 + goto finish; 1.315 + } 1.316 + 1.317 + irv = CRMF_CertRequestSetTemplateField(certReq, inTemplateField, (void*)name); 1.318 + if (irv != SECSuccess) { 1.319 + printf ("Could not add name to cert template\n"); 1.320 + irv = 6; 1.321 + } 1.322 + 1.323 +finish: 1.324 + PORT_Free(nameStr); 1.325 + if (name) 1.326 + CERT_DestroyName(name); 1.327 + return irv; 1.328 +} 1.329 + 1.330 +int 1.331 +CreateCertRequest(TESTKeyPair *pair, long inRequestID) 1.332 +{ 1.333 + CERTCertificate * caCert; 1.334 + CERTSubjectPublicKeyInfo *spki; 1.335 + CRMFCertExtCreationInfo * extInfo; 1.336 + CRMFCertRequest * certReq; 1.337 + CRMFEncryptedKey * encKey; 1.338 + CRMFPKIArchiveOptions * pkiArchOpt; 1.339 + SECAlgorithmID * algID; 1.340 + long serialNumber; 1.341 + long version = 3; 1.342 + SECStatus rv; 1.343 + CRMFValidityCreationInfo validity; 1.344 + unsigned char UIDbuf[UID_BITS / BPB]; 1.345 + SECItem issuerUID = { siBuffer, NULL, 0 }; 1.346 + SECItem subjectUID = { siBuffer, NULL, 0 }; 1.347 + 1.348 + /* len in bits */ 1.349 + issuerUID.data = UIDbuf; 1.350 + issuerUID.len = UID_BITS; 1.351 + subjectUID.data = UIDbuf; 1.352 + subjectUID.len = UID_BITS; 1.353 + 1.354 + pair->certReq = NULL; 1.355 + certReq = CRMF_CreateCertRequest(inRequestID); 1.356 + if (certReq == NULL) { 1.357 + printf ("Could not initialize a certificate request.\n"); 1.358 + return 1; 1.359 + } 1.360 + 1.361 + /* set to version 3 */ 1.362 + rv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion, 1.363 + (void*)(&version)); 1.364 + if (rv != SECSuccess) { 1.365 + printf("Could not add the version number to the " 1.366 + "Certificate Request.\n"); 1.367 + CRMF_DestroyCertRequest(certReq); 1.368 + return 2; 1.369 + } 1.370 + 1.371 + /* set serial number */ 1.372 + if (get_serial_number(&serialNumber) != SECSuccess) { 1.373 + printf ("Could not generate a serial number for cert request.\n"); 1.374 + CRMF_DestroyCertRequest(certReq); 1.375 + return 3; 1.376 + } 1.377 + rv = CRMF_CertRequestSetTemplateField (certReq, crmfSerialNumber, 1.378 + (void*)(&serialNumber)); 1.379 + if (rv != SECSuccess) { 1.380 + printf ("Could not add serial number to certificate template\n."); 1.381 + CRMF_DestroyCertRequest(certReq); 1.382 + return 4; 1.383 + } 1.384 + 1.385 + /* Set issuer name */ 1.386 + rv = InjectCertName(certReq, crmfIssuer, 1.387 + "CN=mozilla CA Shack,O=Information Systems"); 1.388 + if (rv) { 1.389 + printf ("Could not add issuer to cert template\n"); 1.390 + CRMF_DestroyCertRequest(certReq); 1.391 + return 5; 1.392 + } 1.393 + 1.394 + /* Set Subject Name */ 1.395 + rv = InjectCertName(certReq, crmfSubject, 1.396 + "CN=mozilla CA Shack ID,O=Engineering,C=US"); 1.397 + if (rv) { 1.398 + printf ("Could not add Subject to cert template\n"); 1.399 + CRMF_DestroyCertRequest(certReq); 1.400 + return 5; 1.401 + } 1.402 + 1.403 + /* Set Algorithm ID */ 1.404 + algID = PK11_CreatePBEAlgorithmID(SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, 1.405 + 1, NULL); 1.406 + if (algID == NULL) { 1.407 + printf ("Couldn't create algorithm ID\n"); 1.408 + CRMF_DestroyCertRequest(certReq); 1.409 + return 9; 1.410 + } 1.411 + rv = CRMF_CertRequestSetTemplateField(certReq, crmfSigningAlg, (void*)algID); 1.412 + SECOID_DestroyAlgorithmID(algID, PR_TRUE); 1.413 + if (rv != SECSuccess) { 1.414 + printf ("Could not add the signing algorithm to the cert template.\n"); 1.415 + CRMF_DestroyCertRequest(certReq); 1.416 + return 10; 1.417 + } 1.418 + 1.419 + /* Set Validity Dates */ 1.420 + validity.notBefore = ¬Before; 1.421 + validity.notAfter = NULL; 1.422 + notBefore = PR_Now(); 1.423 + rv = CRMF_CertRequestSetTemplateField(certReq, crmfValidity,(void*)(&validity)); 1.424 + if (rv != SECSuccess) { 1.425 + printf ("Could not add validity to cert template\n"); 1.426 + CRMF_DestroyCertRequest(certReq); 1.427 + return 11; 1.428 + } 1.429 + 1.430 + /* Generate a key pair and Add the spki to the request */ 1.431 + spki = GetSubjectPubKeyInfo(pair); 1.432 + if (spki == NULL) { 1.433 + printf ("Could not create a Subject Public Key Info to add\n"); 1.434 + CRMF_DestroyCertRequest(certReq); 1.435 + return 12; 1.436 + } 1.437 + rv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, (void*)spki); 1.438 + SECKEY_DestroySubjectPublicKeyInfo(spki); 1.439 + if (rv != SECSuccess) { 1.440 + printf ("Could not add the public key to the template\n"); 1.441 + CRMF_DestroyCertRequest(certReq); 1.442 + return 13; 1.443 + } 1.444 + 1.445 + /* Set the requested isser Unique ID */ 1.446 + PK11_GenerateRandom(UIDbuf, sizeof UIDbuf); 1.447 + CRMF_CertRequestSetTemplateField(certReq,crmfIssuerUID, (void*)&issuerUID); 1.448 + 1.449 + /* Set the requested Subject Unique ID */ 1.450 + PK11_GenerateRandom(UIDbuf, sizeof UIDbuf); 1.451 + CRMF_CertRequestSetTemplateField(certReq,crmfSubjectUID, (void*)&subjectUID); 1.452 + 1.453 + /* Add extensions - XXX need to understand these magic numbers */ 1.454 + extInfo = GetExtensions(); 1.455 + CRMF_CertRequestSetTemplateField(certReq, crmfExtension, (void*)extInfo); 1.456 + FreeExtInfo(extInfo); 1.457 + 1.458 + /* get the recipient CA's cert */ 1.459 + caCert = CERT_FindCertByNickname(db, caCertName); 1.460 + if (caCert == NULL) { 1.461 + printf ("Could not find the certificate for %s\n", caCertName); 1.462 + CRMF_DestroyCertRequest(certReq); 1.463 + return 50; 1.464 + } 1.465 + encKey = CRMF_CreateEncryptedKeyWithEncryptedValue(pair->privKey, caCert); 1.466 + CERT_DestroyCertificate(caCert); 1.467 + if (encKey == NULL) { 1.468 + printf ("Could not create Encrypted Key with Encrypted Value.\n"); 1.469 + return 14; 1.470 + } 1.471 + pkiArchOpt = CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, encKey); 1.472 + CRMF_DestroyEncryptedKey(encKey); 1.473 + if (pkiArchOpt == NULL) { 1.474 + printf ("Could not create PKIArchiveOptions.\n"); 1.475 + return 15; 1.476 + } 1.477 + rv = CRMF_CertRequestSetPKIArchiveOptions(certReq, pkiArchOpt); 1.478 + CRMF_DestroyPKIArchiveOptions(pkiArchOpt); 1.479 + if (rv != SECSuccess) { 1.480 + printf ("Could not add the PKIArchiveControl to Cert Request.\n"); 1.481 + return 16; 1.482 + } 1.483 + pair->certReq = certReq; 1.484 + return 0; 1.485 +} 1.486 + 1.487 +int 1.488 +Encode(CRMFCertReqMsg *inCertReq1, CRMFCertReqMsg *inCertReq2) 1.489 +{ 1.490 + PRFileDesc *fileDesc; 1.491 + SECStatus rv; 1.492 + int irv = 0; 1.493 + CRMFCertReqMsg *msgArr[3]; 1.494 + char filePath[PATH_LEN]; 1.495 + 1.496 + PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE); 1.497 + fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 1.498 + 0666); 1.499 + if (fileDesc == NULL) { 1.500 + printf ("Could not open file %s\n", filePath); 1.501 + irv = 14; 1.502 + goto finish; 1.503 + } 1.504 + msgArr[0] = inCertReq1; 1.505 + msgArr[1] = inCertReq2; 1.506 + msgArr[2] = NULL; 1.507 + rv = CRMF_EncodeCertReqMessages(msgArr, WriteItOut, (void*)fileDesc); 1.508 + if (rv != SECSuccess) { 1.509 + printf ("An error occurred while encoding.\n"); 1.510 + irv = 15; 1.511 + } 1.512 +finish: 1.513 + PR_Close(fileDesc); 1.514 + return irv; 1.515 +} 1.516 + 1.517 +int 1.518 +AddProofOfPossession(TESTKeyPair *pair, 1.519 + CRMFPOPChoice inPOPChoice) 1.520 +{ 1.521 + 1.522 + switch(inPOPChoice){ 1.523 + case crmfSignature: 1.524 + CRMF_CertReqMsgSetSignaturePOP(pair->certReqMsg, pair->privKey, 1.525 + pair->pubKey, NULL, NULL, &pwdata); 1.526 + break; 1.527 + case crmfRAVerified: 1.528 + CRMF_CertReqMsgSetRAVerifiedPOP(pair->certReqMsg); 1.529 + break; 1.530 + case crmfKeyEncipherment: 1.531 + CRMF_CertReqMsgSetKeyEnciphermentPOP(pair->certReqMsg, 1.532 + crmfSubsequentMessage, 1.533 + crmfChallengeResp, NULL); 1.534 + break; 1.535 + case crmfKeyAgreement: 1.536 + { 1.537 + SECItem pendejo; 1.538 + unsigned char lame[] = { 0xf0, 0x0f, 0xf0, 0x0f, 0xf0 }; 1.539 + 1.540 + pendejo.data = lame; 1.541 + pendejo.len = 5; 1.542 + 1.543 + CRMF_CertReqMsgSetKeyAgreementPOP(pair->certReqMsg, crmfThisMessage, 1.544 + crmfNoSubseqMess, &pendejo); 1.545 + } 1.546 + break; 1.547 + default: 1.548 + return 1; 1.549 + } 1.550 + return 0; 1.551 +} 1.552 + 1.553 + 1.554 +int 1.555 +Decode(void) 1.556 +{ 1.557 + PRFileDesc *fileDesc; 1.558 + CRMFCertReqMsg *certReqMsg; 1.559 + CRMFCertRequest *certReq; 1.560 + CRMFCertReqMessages *certReqMsgs; 1.561 + SECStatus rv; 1.562 + int numMsgs, i; 1.563 + long lame; 1.564 + CRMFGetValidity validity = {NULL, NULL}; 1.565 + SECItem item = { siBuffer, NULL, 0 }; 1.566 + char filePath[PATH_LEN]; 1.567 + 1.568 + PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE); 1.569 + fileDesc = PR_Open(filePath, PR_RDONLY, 0644); 1.570 + if (fileDesc == NULL) { 1.571 + printf ("Could not open file %s\n", filePath); 1.572 + return 214; 1.573 + } 1.574 + rv = SECU_FileToItem(&item, fileDesc); 1.575 + PR_Close(fileDesc); 1.576 + if (rv != SECSuccess) { 1.577 + return 215; 1.578 + } 1.579 + 1.580 + certReqMsgs = CRMF_CreateCertReqMessagesFromDER((char *)item.data, item.len); 1.581 + if (certReqMsgs == NULL) { 1.582 + printf ("Error decoding CertReqMessages.\n"); 1.583 + return 202; 1.584 + } 1.585 + numMsgs = CRMF_CertReqMessagesGetNumMessages(certReqMsgs); 1.586 + if (numMsgs <= 0) { 1.587 + printf ("WARNING: The DER contained %d messages.\n", numMsgs); 1.588 + } 1.589 + for (i=0; i < numMsgs; i++) { 1.590 + SECStatus rv; 1.591 + printf("crmftest: Processing cert request %d\n", i); 1.592 + certReqMsg = CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqMsgs, i); 1.593 + if (certReqMsg == NULL) { 1.594 + printf ("ERROR: Could not access the message at index %d of %s\n", 1.595 + i, filePath); 1.596 + } 1.597 + rv = CRMF_CertReqMsgGetID(certReqMsg, &lame); 1.598 + if (rv) { 1.599 + SECU_PrintError("crmftest", "CRMF_CertReqMsgGetID"); 1.600 + } 1.601 + certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg); 1.602 + if (!certReq) { 1.603 + SECU_PrintError("crmftest", "CRMF_CertReqMsgGetCertRequest"); 1.604 + } 1.605 + rv = CRMF_CertRequestGetCertTemplateValidity(certReq, &validity); 1.606 + if (rv) { 1.607 + SECU_PrintError("crmftest", "CRMF_CertRequestGetCertTemplateValidity"); 1.608 + } 1.609 + if (!validity.notBefore) { 1.610 + /* We encoded a notBefore, so somthing's wrong if it's not here. */ 1.611 + printf("ERROR: Validity period notBefore date missing.\n"); 1.612 + } 1.613 + /* XXX It's all parsed now. We probably should DO SOMETHING with it. 1.614 + ** But nope. We just throw it all away. 1.615 + ** Maybe this was intended to be no more than a decoder test. 1.616 + */ 1.617 + CRMF_DestroyGetValidity(&validity); 1.618 + CRMF_DestroyCertRequest(certReq); 1.619 + CRMF_DestroyCertReqMsg(certReqMsg); 1.620 + } 1.621 + CRMF_DestroyCertReqMessages(certReqMsgs); 1.622 + SECITEM_FreeItem(&item, PR_FALSE); 1.623 + return 0; 1.624 +} 1.625 + 1.626 +int 1.627 +GetBitsFromFile(const char *filePath, SECItem *item) 1.628 +{ 1.629 + PRFileDesc *fileDesc; 1.630 + SECStatus rv; 1.631 + 1.632 + fileDesc = PR_Open(filePath, PR_RDONLY, 0644); 1.633 + if (fileDesc == NULL) { 1.634 + printf ("Could not open file %s\n", filePath); 1.635 + return 14; 1.636 + } 1.637 + 1.638 + rv = SECU_FileToItem(item, fileDesc); 1.639 + PR_Close(fileDesc); 1.640 + 1.641 + if (rv != SECSuccess) { 1.642 + item->data = NULL; 1.643 + item->len = 0; 1.644 + return 15; 1.645 + } 1.646 + return 0; 1.647 +} 1.648 + 1.649 +int 1.650 +DecodeCMMFCertRepContent(char *derFile) 1.651 +{ 1.652 + CMMFCertRepContent *certRepContent; 1.653 + int irv = 0; 1.654 + SECItem fileBits = { siBuffer, NULL, 0 }; 1.655 + 1.656 + GetBitsFromFile(derFile, &fileBits); 1.657 + if (fileBits.data == NULL) { 1.658 + printf("Could not get bits from file %s\n", derFile); 1.659 + return 304; 1.660 + } 1.661 + certRepContent = CMMF_CreateCertRepContentFromDER(db, 1.662 + (char*)fileBits.data, fileBits.len); 1.663 + if (certRepContent == NULL) { 1.664 + printf ("Error while decoding %s\n", derFile); 1.665 + irv = 303; 1.666 + } else { 1.667 + /* That was fun. Now, let's throw it away! */ 1.668 + CMMF_DestroyCertRepContent(certRepContent); 1.669 + } 1.670 + SECITEM_FreeItem(&fileBits, PR_FALSE); 1.671 + return irv; 1.672 +} 1.673 + 1.674 +int 1.675 +EncodeCMMFCertReply(const char *filePath, 1.676 + CERTCertificate *cert, 1.677 + CERTCertList *list) 1.678 +{ 1.679 + int rv = 0; 1.680 + SECStatus srv; 1.681 + PRFileDesc *fileDesc = NULL; 1.682 + CMMFCertRepContent *certRepContent = NULL; 1.683 + CMMFCertResponse *certResp = NULL; 1.684 + CMMFCertResponse *certResponses[3]; 1.685 + 1.686 + certResp = CMMF_CreateCertResponse(0xff123); 1.687 + CMMF_CertResponseSetPKIStatusInfoStatus(certResp, cmmfGranted); 1.688 + 1.689 + CMMF_CertResponseSetCertificate(certResp, cert); 1.690 + 1.691 + certResponses[0] = certResp; 1.692 + certResponses[1] = NULL; 1.693 + certResponses[2] = NULL; 1.694 + 1.695 + certRepContent = CMMF_CreateCertRepContent(); 1.696 + CMMF_CertRepContentSetCertResponses(certRepContent, certResponses, 1); 1.697 + 1.698 + CMMF_CertRepContentSetCAPubs(certRepContent, list); 1.699 + 1.700 + fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 1.701 + 0666); 1.702 + if (fileDesc == NULL) { 1.703 + printf ("Could not open file %s\n", filePath); 1.704 + rv = 400; 1.705 + goto finish; 1.706 + } 1.707 + 1.708 + srv = CMMF_EncodeCertRepContent(certRepContent, WriteItOut, 1.709 + (void*)fileDesc); 1.710 + PR_Close(fileDesc); 1.711 + if (srv != SECSuccess) { 1.712 + printf ("CMMF_EncodeCertRepContent failed,\n"); 1.713 + rv = 401; 1.714 + } 1.715 +finish: 1.716 + if (certRepContent) { 1.717 + CMMF_DestroyCertRepContent(certRepContent); 1.718 + } 1.719 + if (certResp) { 1.720 + CMMF_DestroyCertResponse(certResp); 1.721 + } 1.722 + return rv; 1.723 +} 1.724 + 1.725 + 1.726 +/* Extract the public key from the cert whose nickname is given. */ 1.727 +int 1.728 +extractPubKeyFromNamedCert(const char * nickname, SECKEYPublicKey **pPubKey) 1.729 +{ 1.730 + CERTCertificate *caCert = NULL; 1.731 + SECKEYPublicKey *caPubKey = NULL; 1.732 + int rv = 0; 1.733 + 1.734 + caCert = CERT_FindCertByNickname(db, (char *)nickname); 1.735 + if (caCert == NULL) { 1.736 + printf ("Could not get the certifcate for %s\n", caCertName); 1.737 + rv = 411; 1.738 + goto finish; 1.739 + } 1.740 + caPubKey = CERT_ExtractPublicKey(caCert); 1.741 + if (caPubKey == NULL) { 1.742 + printf ("Could not extract the public from the " 1.743 + "certificate for \n%s\n", caCertName); 1.744 + rv = 412; 1.745 + } 1.746 +finish: 1.747 + *pPubKey = caPubKey; 1.748 + CERT_DestroyCertificate(caCert); 1.749 + caCert = NULL; 1.750 + return rv; 1.751 +} 1.752 + 1.753 +int 1.754 +EncodeCMMFRecoveryMessage(const char * filePath, 1.755 + CERTCertificate *cert, 1.756 + CERTCertList *list) 1.757 +{ 1.758 + SECKEYPublicKey *caPubKey = NULL; 1.759 + SECKEYPrivateKey *privKey = NULL; 1.760 + CMMFKeyRecRepContent *repContent = NULL; 1.761 + PRFileDesc *fileDesc; 1.762 + int rv = 0; 1.763 + SECStatus srv; 1.764 + 1.765 + /* Extract the public key from the cert whose nickname is given in 1.766 + ** the -s option. 1.767 + */ 1.768 + rv = extractPubKeyFromNamedCert( caCertName, &caPubKey); 1.769 + if (rv) 1.770 + goto finish; 1.771 + 1.772 + repContent = CMMF_CreateKeyRecRepContent(); 1.773 + if (repContent == NULL) { 1.774 + printf ("Could not allocate a CMMFKeyRecRepContent structure\n"); 1.775 + rv = 407; 1.776 + goto finish; 1.777 + } 1.778 + srv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(repContent, 1.779 + cmmfGrantedWithMods); 1.780 + if (srv != SECSuccess) { 1.781 + printf ("Error trying to set PKIStatusInfo for " 1.782 + "CMMFKeyRecRepContent.\n"); 1.783 + rv = 406; 1.784 + goto finish; 1.785 + } 1.786 + srv = CMMF_KeyRecRepContentSetNewSignCert(repContent, cert); 1.787 + if (srv != SECSuccess) { 1.788 + printf ("Error trying to set the new signing certificate for " 1.789 + "key recovery\n"); 1.790 + rv = 408; 1.791 + goto finish; 1.792 + } 1.793 + srv = CMMF_KeyRecRepContentSetCACerts(repContent, list); 1.794 + if (srv != SECSuccess) { 1.795 + printf ("Errory trying to add the list of CA certs to the " 1.796 + "CMMFKeyRecRepContent structure.\n"); 1.797 + rv = 409; 1.798 + goto finish; 1.799 + } 1.800 + privKey = PK11_FindKeyByAnyCert(cert, &pwdata); 1.801 + if (privKey == NULL) { 1.802 + printf ("Could not get the private key associated with the\n" 1.803 + "certificate %s\n", personalCert); 1.804 + rv = 410; 1.805 + goto finish; 1.806 + } 1.807 + 1.808 + srv = CMMF_KeyRecRepContentSetCertifiedKeyPair(repContent, cert, privKey, 1.809 + caPubKey); 1.810 + if (srv != SECSuccess) { 1.811 + printf ("Could not set the Certified Key Pair\n"); 1.812 + rv = 413; 1.813 + goto finish; 1.814 + } 1.815 + fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 1.816 + 0666); 1.817 + if (fileDesc == NULL) { 1.818 + printf ("Could not open file %s\n", filePath); 1.819 + rv = 414; 1.820 + goto finish; 1.821 + } 1.822 + 1.823 + srv = CMMF_EncodeKeyRecRepContent(repContent, WriteItOut, 1.824 + (void*)fileDesc); 1.825 + PR_Close(fileDesc); 1.826 + if (srv != SECSuccess) { 1.827 + printf ("CMMF_EncodeKeyRecRepContent failed\n"); 1.828 + rv = 415; 1.829 + } 1.830 +finish: 1.831 + if (privKey) 1.832 + SECKEY_DestroyPrivateKey(privKey); 1.833 + if (caPubKey) 1.834 + SECKEY_DestroyPublicKey(caPubKey); 1.835 + if (repContent) 1.836 + CMMF_DestroyKeyRecRepContent(repContent); 1.837 + return rv; 1.838 +} 1.839 + 1.840 +int 1.841 +decodeCMMFRecoveryMessage(const char * filePath) 1.842 +{ 1.843 + CMMFKeyRecRepContent *repContent = NULL; 1.844 + int rv = 0; 1.845 + SECItem fileBits = { siBuffer, NULL, 0 }; 1.846 + 1.847 + GetBitsFromFile(filePath, &fileBits); 1.848 + if (!fileBits.len) { 1.849 + rv = 451; 1.850 + goto finish; 1.851 + } 1.852 + repContent = 1.853 + CMMF_CreateKeyRecRepContentFromDER(db, (const char *) fileBits.data, 1.854 + fileBits.len); 1.855 + if (repContent == NULL) { 1.856 + printf ("ERROR: CMMF_CreateKeyRecRepContentFromDER failed on file:\n" 1.857 + "\t%s\n", filePath); 1.858 + rv = 452; 1.859 + } 1.860 +finish: 1.861 + if (repContent) { 1.862 + CMMF_DestroyKeyRecRepContent(repContent); 1.863 + } 1.864 + SECITEM_FreeItem(&fileBits, PR_FALSE); 1.865 + return rv; 1.866 +} 1.867 + 1.868 +int 1.869 +DoCMMFStuff(void) 1.870 +{ 1.871 + CERTCertificate *cert = NULL; 1.872 + CERTCertList *list = NULL; 1.873 + int rv = 0; 1.874 + char filePath[PATH_LEN]; 1.875 + 1.876 + /* Do common setup for the following steps. 1.877 + */ 1.878 + PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, "CertRepContent.der"); 1.879 + 1.880 + cert = CERT_FindCertByNickname(db, personalCert); 1.881 + if (cert == NULL) { 1.882 + printf ("Could not find the certificate for %s\n", personalCert); 1.883 + rv = 416; 1.884 + goto finish; 1.885 + } 1.886 + list = CERT_GetCertChainFromCert(cert, PR_Now(), certUsageEmailSigner); 1.887 + if (list == NULL) { 1.888 + printf ("Could not find the certificate chain for %s\n", personalCert); 1.889 + rv = 418; 1.890 + goto finish; 1.891 + } 1.892 + 1.893 + /* a) Generate the CMMF response message, using a user cert named 1.894 + ** by -p option, rather than a cert generated from the CRMF 1.895 + ** request itself. The CMMF message is placed in 1.896 + ** configdir/CertRepContent.der. 1.897 + */ 1.898 + rv = EncodeCMMFCertReply(filePath, cert, list); 1.899 + if (rv != 0) { 1.900 + goto finish; 1.901 + } 1.902 + 1.903 + /* b) Decode the CMMF Cert granting message encoded just above, 1.904 + ** found in configdir/CertRepContent.der. 1.905 + ** This only tests the decoding. The decoded content is discarded. 1.906 + */ 1.907 + rv = DecodeCMMFCertRepContent(filePath); 1.908 + if (rv != 0) { 1.909 + goto finish; 1.910 + } 1.911 + 1.912 + /* c) Generate a CMMF Key Excrow message 1.913 + ** It takes the public and private keys for the cert identified 1.914 + ** by -p nickname, and wraps them with a sym key that is in turn 1.915 + ** wrapped with the pubkey in the CA cert, whose nickname is 1.916 + ** given by the -s option. 1.917 + ** Store the message in configdir/KeyRecRepContent.der 1.918 + */ 1.919 + PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, 1.920 + "KeyRecRepContent.der"); 1.921 + 1.922 + rv = EncodeCMMFRecoveryMessage(filePath, cert, list); 1.923 + if (rv) 1.924 + goto finish; 1.925 + 1.926 + /* d) Decode the CMMF Key Excrow message generated just above. 1.927 + ** Get it from file configdir/KeyRecRepContent.der 1.928 + ** This is just a decoder test. Results are discarded. 1.929 + */ 1.930 + 1.931 + rv = decodeCMMFRecoveryMessage(filePath); 1.932 + 1.933 + finish: 1.934 + if (cert) { 1.935 + CERT_DestroyCertificate(cert); 1.936 + } 1.937 + if (list) { 1.938 + CERT_DestroyCertList(list); 1.939 + } 1.940 + return rv; 1.941 +} 1.942 + 1.943 +static CK_MECHANISM_TYPE 1.944 +mapWrapKeyType(KeyType keyType) 1.945 +{ 1.946 + switch (keyType) { 1.947 + case rsaKey: 1.948 + return CKM_RSA_PKCS; 1.949 + default: 1.950 + break; 1.951 + } 1.952 + return CKM_INVALID_MECHANISM; 1.953 +} 1.954 + 1.955 +#define KNOWN_MESSAGE_LENGTH 20 /*160 bits*/ 1.956 + 1.957 +int 1.958 +DoKeyRecovery( SECKEYPrivateKey *privKey) 1.959 +{ 1.960 +#ifdef DOING_KEY_RECOVERY /* Doesn't compile yet. */ 1.961 + SECKEYPublicKey *pubKey; 1.962 + PK11SlotInfo *slot; 1.963 + unsigned char *ciphertext; 1.964 + unsigned char *text_compared; 1.965 + SECKEYPrivateKey *unwrappedPrivKey; 1.966 + SECKEYPrivateKey *caPrivKey; 1.967 + CMMFKeyRecRepContent *keyRecRep; 1.968 + CMMFCertifiedKeyPair *certKeyPair; 1.969 + CERTCertificate *caCert; 1.970 + CERTCertificate *myCert; 1.971 + SECKEYPublicKey *caPubKey; 1.972 + PRFileDesc *fileDesc; 1.973 + CK_ULONG max_bytes_encrypted; 1.974 + CK_ULONG bytes_encrypted; 1.975 + CK_ULONG bytes_compared; 1.976 + CK_ULONG bytes_decrypted; 1.977 + CK_RV crv; 1.978 + CK_OBJECT_HANDLE id; 1.979 + CK_MECHANISM mech = { CKM_INVALID_MECHANISM, NULL, 0}; 1.980 + SECStatus rv; 1.981 + SECItem fileBits; 1.982 + SECItem nickname; 1.983 + unsigned char plaintext[KNOWN_MESSAGE_LENGTH]; 1.984 + char filePath[PATH_LEN]; 1.985 + static const unsigned char known_message[] = { "Known Crypto Message" }; 1.986 + 1.987 + /*caCert = CERT_FindCertByNickname(db, caCertName);*/ 1.988 + myCert = CERT_FindCertByNickname(db, personalCert); 1.989 + if (myCert == NULL) { 1.990 + printf ("Could not find the certificate for %s\n", personalCert); 1.991 + return 700; 1.992 + } 1.993 + caCert = CERT_FindCertByNickname(db, recoveryEncrypter); 1.994 + if (caCert == NULL) { 1.995 + printf ("Could not find the certificate for %s\n", recoveryEncrypter); 1.996 + return 701; 1.997 + } 1.998 + caPubKey = CERT_ExtractPublicKey(caCert); 1.999 + pubKey = SECKEY_ConvertToPublicKey(privKey); 1.1000 + max_bytes_encrypted = PK11_GetPrivateModulusLen(privKey); 1.1001 + slot = PK11_GetBestSlotWithAttributes(mapWrapKeyType(privKey->keyType), 1.1002 + CKF_ENCRYPT, 0, NULL); 1.1003 + id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE); 1.1004 + 1.1005 + switch(privKey->keyType) { 1.1006 + case rsaKey: 1.1007 + mech.mechanism = CKM_RSA_PKCS; 1.1008 + break; 1.1009 + case dsaKey: 1.1010 + mech.mechanism = CKM_DSA; 1.1011 + break; 1.1012 + case dhKey: 1.1013 + mech.mechanism = CKM_DH_PKCS_DERIVE; 1.1014 + break; 1.1015 + default: 1.1016 + printf ("Bad Key type in key recovery.\n"); 1.1017 + return 512; 1.1018 + 1.1019 + } 1.1020 + PK11_EnterSlotMonitor(slot); 1.1021 + crv = PK11_GETTAB(slot)->C_EncryptInit(slot->session, &mech, id); 1.1022 + if (crv != CKR_OK) { 1.1023 + PK11_ExitSlotMonitor(slot); 1.1024 + PK11_FreeSlot(slot); 1.1025 + printf ("C_EncryptInit failed in KeyRecovery\n"); 1.1026 + return 500; 1.1027 + } 1.1028 + ciphertext = PORT_NewArray(unsigned char, max_bytes_encrypted); 1.1029 + if (ciphertext == NULL) { 1.1030 + PK11_ExitSlotMonitor(slot); 1.1031 + PK11_FreeSlot(slot); 1.1032 + printf ("Could not allocate memory for ciphertext.\n"); 1.1033 + return 501; 1.1034 + } 1.1035 + bytes_encrypted = max_bytes_encrypted; 1.1036 + crv = PK11_GETTAB(slot)->C_Encrypt(slot->session, 1.1037 + known_message, 1.1038 + KNOWN_MESSAGE_LENGTH, 1.1039 + ciphertext, 1.1040 + &bytes_encrypted); 1.1041 + PK11_ExitSlotMonitor(slot); 1.1042 + PK11_FreeSlot(slot); 1.1043 + if (crv != CKR_OK) { 1.1044 + PORT_Free(ciphertext); 1.1045 + return 502; 1.1046 + } 1.1047 + /* Always use the smaller of these two values . . . */ 1.1048 + bytes_compared = ( bytes_encrypted > KNOWN_MESSAGE_LENGTH ) 1.1049 + ? KNOWN_MESSAGE_LENGTH 1.1050 + : bytes_encrypted; 1.1051 + 1.1052 + /* If there was a failure, the plaintext */ 1.1053 + /* goes at the end, therefore . . . */ 1.1054 + text_compared = ( bytes_encrypted > KNOWN_MESSAGE_LENGTH ) 1.1055 + ? (ciphertext + bytes_encrypted - 1.1056 + KNOWN_MESSAGE_LENGTH ) 1.1057 + : ciphertext; 1.1058 + 1.1059 + keyRecRep = CMMF_CreateKeyRecRepContent(); 1.1060 + if (keyRecRep == NULL) { 1.1061 + PORT_Free(ciphertext); 1.1062 + PK11_FreeSlot(slot); 1.1063 + CMMF_DestroyKeyRecRepContent(keyRecRep); 1.1064 + printf ("Could not allocate a CMMFKeyRecRepContent structre.\n"); 1.1065 + return 503; 1.1066 + } 1.1067 + rv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(keyRecRep, 1.1068 + cmmfGranted); 1.1069 + if (rv != SECSuccess) { 1.1070 + PORT_Free(ciphertext); 1.1071 + PK11_FreeSlot(slot); 1.1072 + CMMF_DestroyKeyRecRepContent(keyRecRep); 1.1073 + printf ("Could not set the status for the KeyRecRepContent\n"); 1.1074 + return 504; 1.1075 + } 1.1076 + /* The myCert here should correspond to the certificate corresponding 1.1077 + * to the private key, but for this test any certificate will do. 1.1078 + */ 1.1079 + rv = CMMF_KeyRecRepContentSetCertifiedKeyPair(keyRecRep, myCert, 1.1080 + privKey, caPubKey); 1.1081 + if (rv != SECSuccess) { 1.1082 + PORT_Free(ciphertext); 1.1083 + PK11_FreeSlot(slot); 1.1084 + CMMF_DestroyKeyRecRepContent(keyRecRep); 1.1085 + printf ("Could not set the Certified Key Pair\n"); 1.1086 + return 505; 1.1087 + } 1.1088 + PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, 1.1089 + "KeyRecRepContent.der"); 1.1090 + fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 1.1091 + 0666); 1.1092 + if (fileDesc == NULL) { 1.1093 + PORT_Free(ciphertext); 1.1094 + PK11_FreeSlot(slot); 1.1095 + CMMF_DestroyKeyRecRepContent(keyRecRep); 1.1096 + printf ("Could not open file %s\n", filePath); 1.1097 + return 506; 1.1098 + } 1.1099 + rv = CMMF_EncodeKeyRecRepContent(keyRecRep, WriteItOut, fileDesc); 1.1100 + CMMF_DestroyKeyRecRepContent(keyRecRep); 1.1101 + PR_Close(fileDesc); 1.1102 + 1.1103 + if (rv != SECSuccess) { 1.1104 + PORT_Free(ciphertext); 1.1105 + PK11_FreeSlot(slot); 1.1106 + printf ("Error while encoding CMMFKeyRecRepContent\n"); 1.1107 + return 507; 1.1108 + } 1.1109 + GetBitsFromFile(filePath, &fileBits); 1.1110 + if (fileBits.data == NULL) { 1.1111 + PORT_Free(ciphertext); 1.1112 + PK11_FreeSlot(slot); 1.1113 + printf ("Could not get the bits from file %s\n", filePath); 1.1114 + return 508; 1.1115 + } 1.1116 + keyRecRep = 1.1117 + CMMF_CreateKeyRecRepContentFromDER(db,(const char*)fileBits.data, 1.1118 + fileBits.len); 1.1119 + if (keyRecRep == NULL) { 1.1120 + printf ("Could not decode the KeyRecRepContent in file %s\n", 1.1121 + filePath); 1.1122 + PORT_Free(ciphertext); 1.1123 + PK11_FreeSlot(slot); 1.1124 + return 509; 1.1125 + } 1.1126 + caPrivKey = PK11_FindKeyByAnyCert(caCert, &pwdata); 1.1127 + if (CMMF_KeyRecRepContentGetPKIStatusInfoStatus(keyRecRep) != 1.1128 + cmmfGranted) { 1.1129 + PORT_Free(ciphertext); 1.1130 + PK11_FreeSlot(slot); 1.1131 + CMMF_DestroyKeyRecRepContent(keyRecRep); 1.1132 + printf ("A bad status came back with the " 1.1133 + "KeyRecRepContent structure\n"); 1.1134 + return 510; 1.1135 + } 1.1136 + 1.1137 +#define NICKNAME "Key Recovery Test Key" 1.1138 + nickname.data = (unsigned char*)NICKNAME; 1.1139 + nickname.len = PORT_Strlen(NICKNAME); 1.1140 + 1.1141 + certKeyPair = CMMF_KeyRecRepContentGetCertKeyAtIndex(keyRecRep, 0); 1.1142 + CMMF_DestroyKeyRecRepContent(keyRecRep); 1.1143 + rv = CMMF_CertifiedKeyPairUnwrapPrivKey(certKeyPair, 1.1144 + caPrivKey, 1.1145 + &nickname, 1.1146 + PK11_GetInternalKeySlot(), 1.1147 + db, 1.1148 + &unwrappedPrivKey, &pwdata); 1.1149 + CMMF_DestroyCertifiedKeyPair(certKeyPair); 1.1150 + if (rv != SECSuccess) { 1.1151 + printf ("Unwrapping the private key failed.\n"); 1.1152 + return 511; 1.1153 + } 1.1154 + /*Now let's try to decrypt the ciphertext with the "recovered" key*/ 1.1155 + PK11_EnterSlotMonitor(slot); 1.1156 + crv = 1.1157 + PK11_GETTAB(slot)->C_DecryptInit(unwrappedPrivKey->pkcs11Slot->session, 1.1158 + &mech, 1.1159 + unwrappedPrivKey->pkcs11ID); 1.1160 + if (crv != CKR_OK) { 1.1161 + PK11_ExitSlotMonitor(slot); 1.1162 + PORT_Free(ciphertext); 1.1163 + PK11_FreeSlot(slot); 1.1164 + printf ("Decrypting with the recovered key failed.\n"); 1.1165 + return 513; 1.1166 + } 1.1167 + bytes_decrypted = KNOWN_MESSAGE_LENGTH; 1.1168 + crv = PK11_GETTAB(slot)->C_Decrypt(unwrappedPrivKey->pkcs11Slot->session, 1.1169 + ciphertext, 1.1170 + bytes_encrypted, plaintext, 1.1171 + &bytes_decrypted); 1.1172 + SECKEY_DestroyPrivateKey(unwrappedPrivKey); 1.1173 + PK11_ExitSlotMonitor(slot); 1.1174 + PORT_Free(ciphertext); 1.1175 + if (crv != CKR_OK) { 1.1176 + PK11_FreeSlot(slot); 1.1177 + printf ("Decrypting the ciphertext with recovered key failed.\n"); 1.1178 + return 514; 1.1179 + } 1.1180 + if ((bytes_decrypted != KNOWN_MESSAGE_LENGTH) || 1.1181 + (PORT_Memcmp(plaintext, known_message, KNOWN_MESSAGE_LENGTH) != 0)) { 1.1182 + PK11_FreeSlot(slot); 1.1183 + printf ("The recovered plaintext does not equal the known message:\n" 1.1184 + "\tKnown message: %s\n" 1.1185 + "\tRecovered plaintext: %s\n", known_message, plaintext); 1.1186 + return 515; 1.1187 + } 1.1188 +#endif 1.1189 + return 0; 1.1190 +} 1.1191 + 1.1192 +int 1.1193 +DoChallengeResponse(SECKEYPrivateKey *privKey, 1.1194 + SECKEYPublicKey *pubKey) 1.1195 +{ 1.1196 + CMMFPOPODecKeyChallContent *chalContent = NULL; 1.1197 + CMMFPOPODecKeyRespContent *respContent = NULL; 1.1198 + CERTCertificate *myCert = NULL; 1.1199 + CERTGeneralName *myGenName = NULL; 1.1200 + PLArenaPool *poolp = NULL; 1.1201 + PRFileDesc *fileDesc; 1.1202 + SECItem *publicValue; 1.1203 + SECItem *keyID; 1.1204 + SECKEYPrivateKey *foundPrivKey; 1.1205 + long *randomNums; 1.1206 + int numChallengesFound = 0; 1.1207 + int numChallengesSet = 1; 1.1208 + int i; 1.1209 + long retrieved; 1.1210 + SECStatus rv; 1.1211 + SECItem DecKeyChallBits; 1.1212 + char filePath[PATH_LEN]; 1.1213 + 1.1214 + chalContent = CMMF_CreatePOPODecKeyChallContent(); 1.1215 + myCert = CERT_FindCertByNickname(db, personalCert); 1.1216 + if (myCert == NULL) { 1.1217 + printf ("Could not find the certificate for %s\n", personalCert); 1.1218 + return 900; 1.1219 + } 1.1220 + poolp = PORT_NewArena(1024); 1.1221 + if (poolp == NULL) { 1.1222 + printf("Could no allocate a new arena in DoChallengeResponse\n"); 1.1223 + return 901; 1.1224 + } 1.1225 + myGenName = CERT_GetCertificateNames(myCert, poolp); 1.1226 + if (myGenName == NULL) { 1.1227 + printf ("Could not get the general names for %s certificate\n", 1.1228 + personalCert); 1.1229 + return 902; 1.1230 + } 1.1231 + randomNums = PORT_ArenaNewArray(poolp,long, numChallengesSet); 1.1232 + PK11_GenerateRandom((unsigned char *)randomNums, 1.1233 + numChallengesSet * sizeof(long)); 1.1234 + for (i=0; i<numChallengesSet; i++) { 1.1235 + rv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent, 1.1236 + randomNums[i], 1.1237 + myGenName, 1.1238 + pubKey, 1.1239 + &pwdata); 1.1240 + if (rv != SECSuccess) { 1.1241 + printf ("Could not set the challenge in DoChallengeResponse\n"); 1.1242 + return 903; 1.1243 + } 1.1244 + } 1.1245 + PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyChallContent.der", 1.1246 + configdir); 1.1247 + fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 1.1248 + 0666); 1.1249 + if (fileDesc == NULL) { 1.1250 + printf ("Could not open file %s\n", filePath); 1.1251 + return 904; 1.1252 + } 1.1253 + rv = CMMF_EncodePOPODecKeyChallContent(chalContent,WriteItOut, 1.1254 + (void*)fileDesc); 1.1255 + PR_Close(fileDesc); 1.1256 + CMMF_DestroyPOPODecKeyChallContent(chalContent); 1.1257 + if (rv != SECSuccess) { 1.1258 + printf ("Could not encode the POPODecKeyChallContent.\n"); 1.1259 + return 905; 1.1260 + } 1.1261 + GetBitsFromFile(filePath, &DecKeyChallBits); 1.1262 + chalContent = CMMF_CreatePOPODecKeyChallContentFromDER 1.1263 + ((const char*)DecKeyChallBits.data, DecKeyChallBits.len); 1.1264 + SECITEM_FreeItem(&DecKeyChallBits, PR_FALSE); 1.1265 + if (chalContent == NULL) { 1.1266 + printf ("Could not create the POPODecKeyChallContent from DER\n"); 1.1267 + return 906; 1.1268 + } 1.1269 + numChallengesFound = 1.1270 + CMMF_POPODecKeyChallContentGetNumChallenges(chalContent); 1.1271 + if (numChallengesFound != numChallengesSet) { 1.1272 + printf ("Number of Challenges Found (%d) does not equal the number " 1.1273 + "set (%d)\n", numChallengesFound, numChallengesSet); 1.1274 + return 907; 1.1275 + } 1.1276 + for (i=0; i<numChallengesSet; i++) { 1.1277 + publicValue = CMMF_POPODecKeyChallContentGetPublicValue(chalContent, i); 1.1278 + if (publicValue == NULL) { 1.1279 + printf("Could not get the public value for challenge at index %d\n", 1.1280 + i); 1.1281 + return 908; 1.1282 + } 1.1283 + keyID = PK11_MakeIDFromPubKey(publicValue); 1.1284 + if (keyID == NULL) { 1.1285 + printf ("Could not make the keyID from the public value\n"); 1.1286 + return 909; 1.1287 + } 1.1288 + foundPrivKey = PK11_FindKeyByKeyID(privKey->pkcs11Slot, keyID, &pwdata); 1.1289 + if (foundPrivKey == NULL) { 1.1290 + printf ("Could not find the private key corresponding to the public" 1.1291 + " value.\n"); 1.1292 + return 910; 1.1293 + } 1.1294 + rv = CMMF_POPODecKeyChallContDecryptChallenge(chalContent, i, 1.1295 + foundPrivKey); 1.1296 + if (rv != SECSuccess) { 1.1297 + printf ("Could not decrypt the challenge at index %d\n", i); 1.1298 + return 911; 1.1299 + } 1.1300 + rv = CMMF_POPODecKeyChallContentGetRandomNumber(chalContent, i, 1.1301 + &retrieved); 1.1302 + if (rv != SECSuccess) { 1.1303 + printf ("Could not get the random number from the challenge at " 1.1304 + "index %d\n", i); 1.1305 + return 912; 1.1306 + } 1.1307 + if (retrieved != randomNums[i]) { 1.1308 + printf ("Retrieved the number (%ld), expected (%ld)\n", retrieved, 1.1309 + randomNums[i]); 1.1310 + return 913; 1.1311 + } 1.1312 + } 1.1313 + CMMF_DestroyPOPODecKeyChallContent(chalContent); 1.1314 + PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyRespContent.der", 1.1315 + configdir); 1.1316 + fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 1.1317 + 0666); 1.1318 + if (fileDesc == NULL) { 1.1319 + printf ("Could not open file %s\n", filePath); 1.1320 + return 914; 1.1321 + } 1.1322 + rv = CMMF_EncodePOPODecKeyRespContent(randomNums, numChallengesSet, 1.1323 + WriteItOut, fileDesc); 1.1324 + PR_Close(fileDesc); 1.1325 + if (rv != 0) { 1.1326 + printf ("Could not encode the POPODecKeyRespContent\n"); 1.1327 + return 915; 1.1328 + } 1.1329 + GetBitsFromFile(filePath, &DecKeyChallBits); 1.1330 + respContent = 1.1331 + CMMF_CreatePOPODecKeyRespContentFromDER((const char*)DecKeyChallBits.data, 1.1332 + DecKeyChallBits.len); 1.1333 + if (respContent == NULL) { 1.1334 + printf ("Could not decode the contents of the file %s\n", filePath); 1.1335 + return 916; 1.1336 + } 1.1337 + numChallengesFound = 1.1338 + CMMF_POPODecKeyRespContentGetNumResponses(respContent); 1.1339 + if (numChallengesFound != numChallengesSet) { 1.1340 + printf ("Number of responses found (%d) does not match the number " 1.1341 + "of challenges set (%d)\n", 1.1342 + numChallengesFound, numChallengesSet); 1.1343 + return 917; 1.1344 + } 1.1345 + for (i=0; i<numChallengesSet; i++) { 1.1346 + rv = CMMF_POPODecKeyRespContentGetResponse(respContent, i, &retrieved); 1.1347 + if (rv != SECSuccess) { 1.1348 + printf ("Could not retrieve the response at index %d\n", i); 1.1349 + return 918; 1.1350 + } 1.1351 + if (retrieved != randomNums[i]) { 1.1352 + printf ("Retrieved the number (%ld), expected (%ld)\n", retrieved, 1.1353 + randomNums[i]); 1.1354 + return 919; 1.1355 + } 1.1356 + 1.1357 + } 1.1358 + CMMF_DestroyPOPODecKeyRespContent(respContent); 1.1359 + return 0; 1.1360 +} 1.1361 + 1.1362 +int 1.1363 +MakeCertRequest(TESTKeyPair *pair, CRMFPOPChoice inPOPChoice, long inRequestID) 1.1364 +{ 1.1365 + int irv; 1.1366 + 1.1367 + /* Generate a key pair and a cert request for it. */ 1.1368 + irv = CreateCertRequest(pair, inRequestID); 1.1369 + if (irv != 0 || pair->certReq == NULL) { 1.1370 + goto loser; 1.1371 + } 1.1372 + 1.1373 + pair->certReqMsg = CRMF_CreateCertReqMsg(); 1.1374 + if (!pair->certReqMsg) { 1.1375 + irv = 999; 1.1376 + goto loser; 1.1377 + } 1.1378 + /* copy certReq into certReqMsg */ 1.1379 + CRMF_CertReqMsgSetCertRequest(pair->certReqMsg, pair->certReq); 1.1380 + irv = AddProofOfPossession(pair, inPOPChoice); 1.1381 +loser: 1.1382 + return irv; 1.1383 +} 1.1384 + 1.1385 +int 1.1386 +DestroyPairReqAndMsg(TESTKeyPair *pair) 1.1387 +{ 1.1388 + SECStatus rv = SECSuccess; 1.1389 + int irv = 0; 1.1390 + 1.1391 + if (pair->certReq) { 1.1392 + rv = CRMF_DestroyCertRequest(pair->certReq); 1.1393 + pair->certReq = NULL; 1.1394 + if (rv != SECSuccess) { 1.1395 + printf ("Error when destroying cert request.\n"); 1.1396 + irv = 100; 1.1397 + } 1.1398 + } 1.1399 + if (pair->certReqMsg) { 1.1400 + rv = CRMF_DestroyCertReqMsg(pair->certReqMsg); 1.1401 + pair->certReqMsg = NULL; 1.1402 + if (rv != SECSuccess) { 1.1403 + printf ("Error when destroying cert request msg.\n"); 1.1404 + if (!irv) 1.1405 + irv = 101; 1.1406 + } 1.1407 + } 1.1408 + return irv; 1.1409 +} 1.1410 + 1.1411 +int 1.1412 +DestroyPair(TESTKeyPair *pair) 1.1413 +{ 1.1414 + int irv = 0; 1.1415 + 1.1416 + if (pair->pubKey) { 1.1417 + SECKEY_DestroyPublicKey(pair->pubKey); 1.1418 + pair->pubKey = NULL; 1.1419 + } 1.1420 + if (pair->privKey) { 1.1421 + SECKEY_DestroyPrivateKey(pair->privKey); 1.1422 + pair->privKey = NULL; 1.1423 + } 1.1424 + DestroyPairReqAndMsg(pair); 1.1425 + return irv; 1.1426 +} 1.1427 + 1.1428 +int 1.1429 +DoCRMFRequest(TESTKeyPair *signPair, TESTKeyPair *cryptPair) 1.1430 +{ 1.1431 + int irv, tirv = 0; 1.1432 + 1.1433 + /* Generate a key pair and a cert request for it. */ 1.1434 + irv = MakeCertRequest(signPair, crmfSignature, 0x0f020304); 1.1435 + if (irv != 0 || signPair->certReq == NULL) { 1.1436 + goto loser; 1.1437 + } 1.1438 + 1.1439 + if (!doingDSA) { 1.1440 + irv = MakeCertRequest(cryptPair, crmfKeyAgreement, 0x0f050607); 1.1441 + if (irv != 0 || cryptPair->certReq == NULL) { 1.1442 + goto loser; 1.1443 + } 1.1444 + } 1.1445 + 1.1446 + /* encode the cert request messages into a unified request message. 1.1447 + ** leave it in a file with a fixed name. :( 1.1448 + */ 1.1449 + irv = Encode(signPair->certReqMsg, cryptPair->certReqMsg); 1.1450 + 1.1451 +loser: 1.1452 + if (signPair->certReq) { 1.1453 + tirv = DestroyPairReqAndMsg(signPair); 1.1454 + if (tirv && !irv) 1.1455 + irv = tirv; 1.1456 + } 1.1457 + if (cryptPair->certReq) { 1.1458 + tirv = DestroyPairReqAndMsg(cryptPair); 1.1459 + if (tirv && !irv) 1.1460 + irv = tirv; 1.1461 + } 1.1462 + return irv; 1.1463 +} 1.1464 + 1.1465 +void 1.1466 +Usage (void) 1.1467 +{ 1.1468 + printf ("Usage:\n" 1.1469 + "\tcrmftest -d [Database Directory] -p [Personal Cert]\n" 1.1470 + "\t -e [Encrypter] -s [CA Certificate] [-P password]\n\n" 1.1471 + "\t [crmf] [dsa] [decode] [cmmf] [recover] [challenge]\n" 1.1472 + "\t [-f password_file]\n" 1.1473 + "Database Directory\n" 1.1474 + "\tThis is the directory where the key3.db, cert7.db, and\n" 1.1475 + "\tsecmod.db files are located. This is also the directory\n" 1.1476 + "\twhere the program will place CRMF/CMMF der files\n" 1.1477 + "Personal Cert\n" 1.1478 + "\tThis is the certificate that already exists in the cert\n" 1.1479 + "\tdatabase to use while encoding the response. The private\n" 1.1480 + "\tkey associated with the certificate must also exist in the\n" 1.1481 + "\tkey database.\n" 1.1482 + "Encrypter\n" 1.1483 + "\tThis is the certificate to use when encrypting the the \n" 1.1484 + "\tkey recovery response. The private key for this cert\n" 1.1485 + "\tmust also be present in the key database.\n" 1.1486 + "CA Certificate\n" 1.1487 + "\tThis is the nickname of the certificate to use as the\n" 1.1488 + "\tCA when doing all of the encoding.\n"); 1.1489 +} 1.1490 + 1.1491 +#define TEST_MAKE_CRMF_REQ 0x0001 1.1492 +#define TEST_USE_DSA 0x0002 1.1493 +#define TEST_DECODE_CRMF_REQ 0x0004 1.1494 +#define TEST_DO_CMMF_STUFF 0x0008 1.1495 +#define TEST_KEY_RECOVERY 0x0010 1.1496 +#define TEST_CHALLENGE_RESPONSE 0x0020 1.1497 + 1.1498 +SECStatus 1.1499 +parsePositionalParam(const char * arg, PRUint32 *flags) 1.1500 +{ 1.1501 + if (!strcmp(arg, "crmf")) { 1.1502 + *flags |= TEST_MAKE_CRMF_REQ; 1.1503 + } else if (!strcmp(arg, "dsa")) { 1.1504 + *flags |= TEST_MAKE_CRMF_REQ | TEST_USE_DSA; 1.1505 + doingDSA = PR_TRUE; 1.1506 + } else if (!strcmp(arg, "decode")) { 1.1507 + *flags |= TEST_DECODE_CRMF_REQ; 1.1508 + } else if (!strcmp(arg, "cmmf")) { 1.1509 + *flags |= TEST_DO_CMMF_STUFF; 1.1510 + } else if (!strcmp(arg, "recover")) { 1.1511 + *flags |= TEST_KEY_RECOVERY; 1.1512 + } else if (!strcmp(arg, "challenge")) { 1.1513 + *flags |= TEST_CHALLENGE_RESPONSE; 1.1514 + } else { 1.1515 + printf("unknown positional paremeter: %s\n", arg); 1.1516 + return SECFailure; 1.1517 + } 1.1518 + return SECSuccess; 1.1519 +} 1.1520 + 1.1521 +/* it's not clear, in some cases, whether the desired key is from 1.1522 +** the sign pair or the crypt pair, so we're guessing in some places. 1.1523 +** This define serves to remind us of the places where we're guessing. 1.1524 +*/ 1.1525 +#define WHICH_KEY cryptPair 1.1526 + 1.1527 +int 1.1528 +main(int argc, char **argv) 1.1529 +{ 1.1530 + TESTKeyPair signPair, cryptPair; 1.1531 + PLOptState *optstate; 1.1532 + PLOptStatus status; 1.1533 + char *password = NULL; 1.1534 + char *pwfile = NULL; 1.1535 + int irv = 0; 1.1536 + PRUint32 flags = 0; 1.1537 + SECStatus rv; 1.1538 + PRBool nssInit = PR_FALSE; 1.1539 + PRBool pArg = PR_FALSE; 1.1540 + PRBool eArg = PR_FALSE; 1.1541 + PRBool sArg = PR_FALSE; 1.1542 + PRBool PArg = PR_FALSE; 1.1543 + 1.1544 + memset( &signPair, 0, sizeof signPair); 1.1545 + memset( &cryptPair, 0, sizeof cryptPair); 1.1546 + printf ("\ncrmftest v1.0\n"); 1.1547 + optstate = PL_CreateOptState(argc, argv, "d:p:e:s:P:f:"); 1.1548 + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.1549 + switch (optstate->option) { 1.1550 + case 'd': 1.1551 + configdir = PORT_Strdup(optstate->value); 1.1552 + rv = NSS_Init(configdir); 1.1553 + if (rv != SECSuccess) { 1.1554 + printf ("NSS_Init (-d) failed\n"); 1.1555 + return 101; 1.1556 + } 1.1557 + nssInit = PR_TRUE; 1.1558 + break; 1.1559 + case 'p': 1.1560 + personalCert = PORT_Strdup(optstate->value); 1.1561 + if (personalCert == NULL) { 1.1562 + printf ("-p failed\n"); 1.1563 + return 603; 1.1564 + } 1.1565 + pArg = PR_TRUE; 1.1566 + break; 1.1567 + case 'e': 1.1568 + recoveryEncrypter = PORT_Strdup(optstate->value); 1.1569 + if (recoveryEncrypter == NULL) { 1.1570 + printf ("-e failed\n"); 1.1571 + return 602; 1.1572 + } 1.1573 + eArg = PR_TRUE; 1.1574 + break; 1.1575 + case 's': 1.1576 + caCertName = PORT_Strdup(optstate->value); 1.1577 + if (caCertName == NULL) { 1.1578 + printf ("-s failed\n"); 1.1579 + return 604; 1.1580 + } 1.1581 + sArg = PR_TRUE; 1.1582 + break; 1.1583 + case 'P': 1.1584 + password = PORT_Strdup(optstate->value); 1.1585 + if (password == NULL) { 1.1586 + printf ("-P failed\n"); 1.1587 + return 606; 1.1588 + } 1.1589 + pwdata.source = PW_PLAINTEXT; 1.1590 + pwdata.data = password; 1.1591 + PArg = PR_TRUE; 1.1592 + break; 1.1593 + case 'f': 1.1594 + pwfile = PORT_Strdup(optstate->value); 1.1595 + if (pwfile == NULL) { 1.1596 + printf ("-f failed\n"); 1.1597 + return 607; 1.1598 + } 1.1599 + pwdata.source = PW_FROMFILE; 1.1600 + pwdata.data = pwfile; 1.1601 + break; 1.1602 + case 0: /* positional parameter */ 1.1603 + rv = parsePositionalParam(optstate->value, &flags); 1.1604 + if (rv) { 1.1605 + printf ("bad positional parameter.\n"); 1.1606 + return 605; 1.1607 + } 1.1608 + break; 1.1609 + default: 1.1610 + Usage(); 1.1611 + return 601; 1.1612 + } 1.1613 + } 1.1614 + PL_DestroyOptState(optstate); 1.1615 + if (status == PL_OPT_BAD || !nssInit) { 1.1616 + Usage(); 1.1617 + return 600; 1.1618 + } 1.1619 + if (!flags) 1.1620 + flags = ~ TEST_USE_DSA; 1.1621 + db = CERT_GetDefaultCertDB(); 1.1622 + InitPKCS11(); 1.1623 + 1.1624 + if (flags & TEST_MAKE_CRMF_REQ) { 1.1625 + printf("Generating CRMF request\n"); 1.1626 + irv = DoCRMFRequest(&signPair, &cryptPair); 1.1627 + if (irv) 1.1628 + goto loser; 1.1629 + } 1.1630 + 1.1631 + if (flags & TEST_DECODE_CRMF_REQ) { 1.1632 + printf("Decoding CRMF request\n"); 1.1633 + irv = Decode(); 1.1634 + if (irv != 0) { 1.1635 + printf("Error while decoding\n"); 1.1636 + goto loser; 1.1637 + } 1.1638 + } 1.1639 + 1.1640 + if (flags & TEST_DO_CMMF_STUFF) { 1.1641 + printf("Doing CMMF Stuff\n"); 1.1642 + if ((irv = DoCMMFStuff()) != 0) { 1.1643 + printf ("CMMF tests failed.\n"); 1.1644 + goto loser; 1.1645 + } 1.1646 + } 1.1647 + 1.1648 + if (flags & TEST_KEY_RECOVERY) { 1.1649 + /* Requires some other options be set. 1.1650 + ** Once we know exactly what hey are, test for them here. 1.1651 + */ 1.1652 + printf("Doing Key Recovery\n"); 1.1653 + irv = DoKeyRecovery(WHICH_KEY.privKey); 1.1654 + if (irv != 0) { 1.1655 + printf ("Error doing key recovery\n"); 1.1656 + goto loser; 1.1657 + } 1.1658 + } 1.1659 + 1.1660 + if (flags & TEST_CHALLENGE_RESPONSE) { 1.1661 + printf("Doing Challenge / Response\n"); 1.1662 + irv = DoChallengeResponse(WHICH_KEY.privKey, WHICH_KEY.pubKey); 1.1663 + if (irv != 0) { 1.1664 + printf ("Error doing challenge-response\n"); 1.1665 + goto loser; 1.1666 + } 1.1667 + } 1.1668 + printf ("Exiting successfully!!!\n\n"); 1.1669 + irv = 0; 1.1670 + 1.1671 + loser: 1.1672 + DestroyPair(&signPair); 1.1673 + DestroyPair(&cryptPair); 1.1674 + rv = NSS_Shutdown(); 1.1675 + if (rv) { 1.1676 + printf("NSS_Shutdown did not shutdown cleanly!\n"); 1.1677 + } 1.1678 + PORT_Free(configdir); 1.1679 + if (irv) 1.1680 + printf("crmftest returning %d\n", irv); 1.1681 + return irv; 1.1682 +}