tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }