pk11importtest.c (13115B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "secutil.h" 6 #include "secmod.h" 7 #include "cert.h" 8 #include "secoid.h" 9 #include "nss.h" 10 #include "pk11pub.h" 11 #include "pk11pqg.h" 12 13 /* NSPR 2.0 header files */ 14 #include "prinit.h" 15 #include "prprf.h" 16 #include "prsystem.h" 17 #include "prmem.h" 18 /* Portable layer header files */ 19 #include "plstr.h" 20 21 SECOidData * 22 getCurveFromString(char *curve_name) 23 { 24 SECOidTag tag = SEC_OID_SECG_EC_SECP256R1; 25 26 if (PORT_Strcasecmp(curve_name, "NISTP256") == 0) { 27 } else if (PORT_Strcasecmp(curve_name, "NISTP384") == 0) { 28 tag = SEC_OID_SECG_EC_SECP384R1; 29 } else if (PORT_Strcasecmp(curve_name, "NISTP521") == 0) { 30 tag = SEC_OID_SECG_EC_SECP521R1; 31 } else if (PORT_Strcasecmp(curve_name, "Curve25519") == 0) { 32 tag = SEC_OID_CURVE25519; 33 } 34 return SECOID_FindOIDByTag(tag); 35 } 36 37 void 38 dumpItem(const char *label, const SECItem *item) 39 { 40 int i; 41 printf("%s = [%d bytes] {", label, item->len); 42 for (i = 0; i < item->len; i++) { 43 if ((i & 0xf) == 0) 44 printf("\n "); 45 else 46 printf(", "); 47 printf("%02x", item->data[i]); 48 } 49 printf("};\n"); 50 } 51 52 SECStatus 53 handleEncryptedPrivateImportTest(char *progName, PK11SlotInfo *slot, 54 char *testname, CK_MECHANISM_TYPE genMech, void *params, void *pwArgs) 55 { 56 SECStatus rv = SECSuccess; 57 SECItem privID = { 0 }; 58 SECItem pubID = { 0 }; 59 SECItem pubValue = { 0 }; 60 SECItem pbePwItem = { 0 }; 61 SECItem nickname = { 0 }; 62 SECItem token = { 0 }; 63 SECKEYPublicKey *pubKey = NULL; 64 SECKEYPrivateKey *privKey = NULL; 65 PK11GenericObject *objs = NULL; 66 PK11GenericObject *obj = NULL; 67 SECKEYEncryptedPrivateKeyInfo *epki = NULL; 68 PRBool keyFound = 0; 69 KeyType keyType; 70 71 fprintf(stderr, "Testing %s PrivateKeyImport ***********************\n", 72 testname); 73 74 /* generate a temp key */ 75 privKey = PK11_GenerateKeyPair(slot, genMech, params, &pubKey, 76 PR_FALSE, PR_TRUE, pwArgs); 77 if (privKey == NULL) { 78 SECU_PrintError(progName, "PK11_GenerateKeyPair Failed"); 79 goto cleanup; 80 } 81 82 /* wrap the temp key */ 83 pbePwItem.data = (unsigned char *)"pw"; 84 pbePwItem.len = 2; 85 epki = PK11_ExportEncryptedPrivKeyInfo(slot, SEC_OID_AES_256_CBC, 86 &pbePwItem, privKey, 1, NULL); 87 if (epki == NULL) { 88 SECU_PrintError(progName, "PK11_ExportEncryptedPrivKeyInfo Failed"); 89 goto cleanup; 90 } 91 92 /* Save the public value, which we will need on import */ 93 keyType = pubKey->keyType; 94 switch (keyType) { 95 case rsaKey: 96 SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.rsa.modulus); 97 break; 98 case dhKey: 99 SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dh.publicValue); 100 break; 101 case dsaKey: 102 SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dsa.publicValue); 103 break; 104 case ecKey: 105 SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.ec.publicValue); 106 break; 107 default: 108 fprintf(stderr, "Unknown keytype = %d\n", keyType); 109 goto cleanup; 110 } 111 if (pubValue.data == NULL) { 112 SECU_PrintError(progName, "Unable to allocate memory"); 113 goto cleanup; 114 } 115 dumpItem("pubValue", &pubValue); 116 117 /* when Asymetric keys represent session keys, those session keys are 118 * destroyed when we destroy the Asymetric key representations */ 119 SECKEY_DestroyPublicKey(pubKey); 120 pubKey = NULL; 121 SECKEY_DestroyPrivateKey(privKey); 122 privKey = NULL; 123 124 /* unwrap the temp key as a perm */ 125 nickname.data = (unsigned char *)"testKey"; 126 nickname.len = sizeof("testKey"); 127 rv = PK11_ImportEncryptedPrivateKeyInfoAndReturnKey( 128 slot, epki, &pbePwItem, &nickname, &pubValue, 129 PR_TRUE, PR_TRUE, keyType, 0, &privKey, NULL); 130 if (rv != SECSuccess) { 131 SECU_PrintError(progName, "PK11_ImportEncryptedPrivateKeyInfo Failed"); 132 goto cleanup; 133 } 134 135 /* verify the public key exists */ 136 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey, CKA_ID, &privID); 137 if (rv != SECSuccess) { 138 SECU_PrintError(progName, 139 "Couldn't read CKA_ID from pub key, checking next key"); 140 goto cleanup; 141 } 142 dumpItem("privKey CKA_ID", &privID); 143 objs = PK11_FindGenericObjects(slot, CKO_PUBLIC_KEY); 144 for (obj = objs; obj; obj = PK11_GetNextGenericObject(obj)) { 145 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_ID, &pubID); 146 if (rv != SECSuccess) { 147 SECU_PrintError(progName, 148 "Couldn't read CKA_ID from object, checking next key"); 149 continue; 150 } 151 dumpItem("pubKey CKA_ID", &pubID); 152 if (!SECITEM_ItemsAreEqual(&privID, &pubID)) { 153 fprintf(stderr, 154 "CKA_ID does not match priv key, checking next key\n"); 155 SECITEM_FreeItem(&pubID, PR_FALSE); 156 continue; 157 } 158 SECITEM_FreeItem(&pubID, PR_FALSE); 159 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_TOKEN, &token); 160 if (rv == SECSuccess) { 161 if (token.len == 1) { 162 keyFound = token.data[0]; 163 } 164 SECITEM_FreeItem(&token, PR_FALSE); 165 } 166 if (keyFound) { 167 printf("matching public key found\n"); 168 break; 169 } 170 printf("Matching key was not a token key, checking next key\n"); 171 } 172 173 cleanup: 174 if (objs) { 175 PK11_DestroyGenericObjects(objs); 176 } 177 SECITEM_FreeItem(&pubValue, PR_FALSE); 178 SECITEM_FreeItem(&privID, PR_FALSE); 179 if (epki && epki->arena) { 180 PORT_FreeArena(epki->arena, PR_TRUE); 181 } 182 SECKEY_DestroyPublicKey(pubKey); 183 SECKEY_DestroyPrivateKey(privKey); 184 fprintf(stderr, "%s PrivateKeyImport %s ***********************\n", 185 testname, keyFound ? "PASSED" : "FAILED"); 186 return keyFound ? SECSuccess : SECFailure; 187 } 188 189 static const char *const usageInfo[] = { 190 "pk11import - test PK11_PrivateKeyImport()", 191 "Options:", 192 " -d certdir directory containing cert database", 193 " -k keysize size of the rsa, dh, and dsa key to test (default 1024)", 194 " -C ecc_curve ecc curve (default )", 195 " -f pwFile file to fetch the password from", 196 " -p pwString password", 197 " -r skip rsa test", 198 " -D skip dsa test", 199 " -h skip dh test", 200 " -e skip ec test", 201 }; 202 static int nUsageInfo = sizeof(usageInfo) / sizeof(char *); 203 204 static void 205 Usage(char *progName, FILE *outFile) 206 { 207 int i; 208 fprintf(outFile, "Usage: %s [ commands ] options\n", progName); 209 for (i = 0; i < nUsageInfo; i++) 210 fprintf(outFile, "%s\n", usageInfo[i]); 211 exit(-1); 212 } 213 214 enum { 215 opt_CertDir, 216 opt_KeySize, 217 opt_ECCurve, 218 opt_PWFile, 219 opt_PWString, 220 opt_NoRSA, 221 opt_NoDSA, 222 opt_NoEC, 223 opt_NoDH 224 }; 225 226 static secuCommandFlag options[] = { 227 { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, 228 { /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE }, 229 { /* opt_ECCurve */ 'C', PR_TRUE, 0, PR_FALSE }, 230 { /* opt_PWFile */ 'f', PR_TRUE, 0, PR_FALSE }, 231 { /* opt_PWString */ 'p', PR_TRUE, 0, PR_FALSE }, 232 { /* opt_NORSA */ 'r', PR_TRUE, 0, PR_FALSE }, 233 { /* opt_NoDSA */ 'D', PR_TRUE, 0, PR_FALSE }, 234 { /* opt_NoDH */ 'h', PR_TRUE, 0, PR_FALSE }, 235 { /* opt_NoEC */ 'e', PR_TRUE, 0, PR_FALSE }, 236 }; 237 238 int 239 main(int argc, char **argv) 240 { 241 char *progName; 242 SECStatus rv; 243 secuCommand args; 244 PK11SlotInfo *slot = NULL; 245 PRBool failed = PR_FALSE; 246 secuPWData pwArgs = { PW_NONE, 0 }; 247 PRBool doRSA = PR_TRUE; 248 PRBool doDSA = PR_TRUE; 249 PRBool doDH = PR_FALSE; /* NSS currently can't export wrapped DH keys */ 250 PRBool doEC = PR_TRUE; 251 PQGParams *pqgParams = NULL; 252 int keySize; 253 254 args.numCommands = 0; 255 args.numOptions = sizeof(options) / sizeof(secuCommandFlag); 256 args.commands = NULL; 257 args.options = options; 258 259 #ifdef XP_PC 260 progName = strrchr(argv[0], '\\'); 261 #else 262 progName = strrchr(argv[0], '/'); 263 #endif 264 progName = progName ? progName + 1 : argv[0]; 265 266 rv = SECU_ParseCommandLine(argc, argv, progName, &args); 267 if (SECSuccess != rv) { 268 Usage(progName, stderr); 269 } 270 271 /* Set the certdb directory (default is ~/.netscape) */ 272 rv = NSS_InitReadWrite(SECU_ConfigDirectory(args.options[opt_CertDir].arg)); 273 if (rv != SECSuccess) { 274 SECU_PrintPRandOSError(progName); 275 return 255; 276 } 277 PK11_SetPasswordFunc(SECU_GetModulePassword); 278 279 /* below here, goto cleanup */ 280 SECU_RegisterDynamicOids(); 281 282 /* handle the arguments */ 283 if (args.options[opt_PWFile].arg) { 284 pwArgs.source = PW_FROMFILE; 285 pwArgs.data = args.options[opt_PWFile].arg; 286 } 287 if (args.options[opt_PWString].arg) { 288 pwArgs.source = PW_PLAINTEXT; 289 pwArgs.data = args.options[opt_PWString].arg; 290 } 291 if (args.options[opt_NoRSA].activated) { 292 doRSA = PR_FALSE; 293 } 294 if (args.options[opt_NoDSA].activated) { 295 doDSA = PR_FALSE; 296 } 297 if (args.options[opt_NoDH].activated) { 298 doDH = PR_FALSE; 299 } 300 if (args.options[opt_NoEC].activated) { 301 doEC = PR_FALSE; 302 } 303 304 slot = PK11_GetInternalKeySlot(); 305 if (slot == NULL) { 306 SECU_PrintError(progName, "Couldn't find the internal key slot\n"); 307 return 255; 308 } 309 rv = PK11_Authenticate(slot, PR_TRUE, &pwArgs); 310 if (rv != SECSuccess) { 311 SECU_PrintError(progName, "Failed to log into slot"); 312 PK11_FreeSlot(slot); 313 return 255; 314 } 315 316 keySize = 1024; 317 if (args.options[opt_KeySize].activated && 318 args.options[opt_KeySize].arg) { 319 keySize = atoi(args.options[opt_KeySize].arg); 320 } 321 322 if (doDSA || doDH) { 323 PQGVerify *pqgVfy; 324 rv = PK11_PQG_ParamGenV2(keySize, 0, keySize / 16, &pqgParams, &pqgVfy); 325 if (rv == SECSuccess) { 326 PK11_PQG_DestroyVerify(pqgVfy); 327 } else { 328 SECU_PrintError(progName, 329 "PK11_PQG_ParamGenV2 failed, can't test DH or DSA"); 330 doDSA = doDH = PR_FALSE; 331 failed = PR_TRUE; 332 } 333 } 334 335 if (doRSA) { 336 PK11RSAGenParams rsaParams; 337 rsaParams.keySizeInBits = keySize; 338 rsaParams.pe = 0x010001; 339 rv = handleEncryptedPrivateImportTest(progName, slot, "RSA", 340 CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, &pwArgs); 341 if (rv != SECSuccess) { 342 fprintf(stderr, "RSA Import Failed!\n"); 343 failed = PR_TRUE; 344 } 345 } 346 if (doDSA) { 347 rv = handleEncryptedPrivateImportTest(progName, slot, "DSA", 348 CKM_DSA_KEY_PAIR_GEN, pqgParams, &pwArgs); 349 if (rv != SECSuccess) { 350 fprintf(stderr, "DSA Import Failed!\n"); 351 failed = PR_TRUE; 352 } 353 } 354 if (doDH) { 355 SECKEYDHParams dhParams; 356 dhParams.prime = pqgParams->prime; 357 dhParams.base = pqgParams->base; 358 rv = handleEncryptedPrivateImportTest(progName, slot, "DH", 359 CKM_DH_PKCS_KEY_PAIR_GEN, &dhParams, &pwArgs); 360 if (rv != SECSuccess) { 361 fprintf(stderr, "DH Import Failed!\n"); 362 failed = PR_TRUE; 363 } 364 } 365 if (doEC) { 366 SECKEYECParams ecParams; 367 SECOidData *curve = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); 368 if (args.options[opt_ECCurve].activated && 369 args.options[opt_ECCurve].arg) { 370 curve = getCurveFromString(args.options[opt_ECCurve].arg); 371 } 372 ecParams.data = PORT_Alloc(curve->oid.len + 2); 373 if (ecParams.data == NULL) { 374 rv = SECFailure; 375 goto ec_failed; 376 } 377 ecParams.data[0] = SEC_ASN1_OBJECT_ID; 378 ecParams.data[1] = (unsigned char)curve->oid.len; 379 PORT_Memcpy(&ecParams.data[2], curve->oid.data, curve->oid.len); 380 ecParams.len = curve->oid.len + 2; 381 rv = handleEncryptedPrivateImportTest(progName, slot, "ECC", 382 CKM_EC_KEY_PAIR_GEN, &ecParams, &pwArgs); 383 PORT_Free(ecParams.data); 384 ec_failed: 385 if (rv != SECSuccess) { 386 fprintf(stderr, "ECC Import Failed!\n"); 387 failed = PR_TRUE; 388 } 389 } 390 391 if (pqgParams) { 392 PK11_PQG_DestroyParams(pqgParams); 393 } 394 395 if (slot) { 396 PK11_FreeSlot(slot); 397 } 398 399 rv = NSS_Shutdown(); 400 if (rv != SECSuccess) { 401 fprintf(stderr, "Shutdown failed\n"); 402 SECU_PrintPRandOSError(progName); 403 return 255; 404 } 405 406 return failed ? 1 : 0; 407 }