Example #1
0
SECStatus
crmf_encrypted_value_unwrap_priv_key(PLArenaPool *poolp,
                                     CRMFEncryptedValue *encValue,
                                     SECKEYPrivateKey *privKey,
                                     SECKEYPublicKey *newPubKey,
                                     SECItem *nickname,
                                     PK11SlotInfo *slot,
                                     unsigned char keyUsage,
                                     SECKEYPrivateKey **unWrappedKey,
                                     void *wincx)
{
    PK11SymKey *wrappingKey = NULL;
    CK_MECHANISM_TYPE wrapMechType;
    SECOidTag oidTag;
    SECItem *params = NULL, *publicValue = NULL;
    int keySize, origLen;
    CK_KEY_TYPE keyType;
    CK_ATTRIBUTE_TYPE *usage = NULL;
    CK_ATTRIBUTE_TYPE rsaUsage[] = {
        CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER
    };
    CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN };
    CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE };
    int usageCount = 0;

    oidTag = SECOID_GetAlgorithmTag(encValue->symmAlg);
    wrapMechType = crmf_get_pad_mech_from_tag(oidTag);
    keySize = crmf_get_key_size_from_mech(wrapMechType);
    wrappingKey = PK11_PubUnwrapSymKey(privKey, &encValue->encSymmKey,
                                       wrapMechType, CKA_UNWRAP, keySize);
    if (wrappingKey == NULL) {
        goto loser;
    } /* Make the length a byte length instead of bit length*/
    params = (encValue->symmAlg != NULL) ? crmf_decode_params(&encValue->symmAlg->parameters)
             : NULL;
    origLen = encValue->encValue.len;
    encValue->encValue.len = CRMF_BITS_TO_BYTES(origLen);
    publicValue = crmf_get_public_value(newPubKey, NULL);
    switch (newPubKey->keyType) {
    default:
    case rsaKey:
        keyType = CKK_RSA;
        switch (keyUsage & (KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE)) {
        case KU_KEY_ENCIPHERMENT:
            usage = rsaUsage;
            usageCount = 2;
            break;
        case KU_DIGITAL_SIGNATURE:
            usage = &rsaUsage[2];
            usageCount = 2;
            break;
        case KU_KEY_ENCIPHERMENT |
                KU_DIGITAL_SIGNATURE:
        case 0: /* default to everything */
            usage = rsaUsage;
            usageCount = 4;
            break;
        }
        break;
    case dhKey:
        keyType = CKK_DH;
        usage = dhUsage;
        usageCount = sizeof(dhUsage) / sizeof(dhUsage[0]);
        break;
    case dsaKey:
        keyType = CKK_DSA;
        usage = dsaUsage;
        usageCount = sizeof(dsaUsage) / sizeof(dsaUsage[0]);
        break;
    }
    PORT_Assert(usage != NULL);
    PORT_Assert(usageCount != 0);
    *unWrappedKey = PK11_UnwrapPrivKey(slot, wrappingKey, wrapMechType, params,
                                       &encValue->encValue, nickname,
                                       publicValue, PR_TRUE, PR_TRUE,
                                       keyType, usage, usageCount, wincx);
    encValue->encValue.len = origLen;
    if (*unWrappedKey == NULL) {
        goto loser;
    }
    SECITEM_FreeItem(publicValue, PR_TRUE);
    if (params != NULL) {
        SECITEM_FreeItem(params, PR_TRUE);
    }
    PK11_FreeSymKey(wrappingKey);
    return SECSuccess;
loser:
    *unWrappedKey = NULL;
    return SECFailure;
}
Example #2
0
static int
cmmf_create_witness_and_challenge(PRArenaPool     *poolp,
                                  CMMFChallenge   *challenge,
                                  long             inRandom,
                                  SECItem         *senderDER,
                                  SECKEYPublicKey *inPubKey,
                                  void            *passwdArg)
{
    SECItem       *encodedRandNum;
    SECItem        encodedRandStr = {siBuffer, NULL, 0};
    SECItem       *dummy;
    unsigned char *randHash, *senderHash, *encChal=NULL;
    unsigned       modulusLen = 0;
    SECStatus      rv = SECFailure;
    CMMFRand       randStr= { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}};
    PK11SlotInfo  *slot;
    PK11SymKey    *symKey = NULL;
    CK_OBJECT_HANDLE id;
    CERTSubjectPublicKeyInfo *spki = NULL;


    encodedRandNum = SEC_ASN1EncodeInteger(poolp, &challenge->randomNumber,
                                           inRandom);
    encodedRandNum = &challenge->randomNumber;
    randHash   = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
    senderHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
    if (randHash == NULL) {
        goto loser;
    }
    rv = PK11_HashBuf(SEC_OID_SHA1, randHash, encodedRandNum->data,
                      (PRUint32)encodedRandNum->len);
    if (rv != SECSuccess) {
        goto loser;
    }
    rv = PK11_HashBuf(SEC_OID_SHA1, senderHash, senderDER->data,
                      (PRUint32)senderDER->len);
    if (rv != SECSuccess) {
        goto loser;
    }
    challenge->witness.data = randHash;
    challenge->witness.len  = SHA1_LENGTH;

    randStr.integer    = *encodedRandNum;
    randStr.senderHash.data = senderHash;
    randStr.senderHash.len  = SHA1_LENGTH;
    dummy = SEC_ASN1EncodeItem(NULL, &encodedRandStr, &randStr,
                               CMMFRandTemplate);
    if (dummy != &encodedRandStr) {
        rv = SECFailure;
        goto loser;
    }
    /* XXXX Now I have to encrypt encodedRandStr and stash it away. */
    modulusLen = SECKEY_PublicKeyStrength(inPubKey);
    encChal = PORT_ArenaNewArray(poolp, unsigned char, modulusLen);
    if (encChal == NULL) {
        rv = SECFailure;
        goto loser;
    }
    slot =PK11_GetBestSlotWithAttributes(CKM_RSA_PKCS, CKF_WRAP, 0, passwdArg);
    if (slot == NULL) {
        rv = SECFailure;
        goto loser;
    }
    id = PK11_ImportPublicKey(slot, inPubKey, PR_FALSE);
    /* In order to properly encrypt the data, we import as a symmetric
     * key, and then wrap that key.  That in essence encrypts the data.
     * This is the method recommended in the PK11 world in order
     * to prevent threading issues as well as breaking any other semantics
     * the PK11 libraries depend on.
     */
    symKey = PK11_ImportSymKey(slot, CKM_RSA_PKCS, PK11_OriginGenerated,
                               CKA_VALUE, &encodedRandStr, passwdArg);
    if (symKey == NULL) {
        rv = SECFailure;
        goto loser;
    }
    challenge->challenge.data = encChal;
    challenge->challenge.len  = modulusLen;
    rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, inPubKey, symKey,
                            &challenge->challenge);
    PK11_FreeSlot(slot);
    if (rv != SECSuccess) {
        goto loser;
    }
    rv = SECITEM_CopyItem(poolp, &challenge->senderDER, senderDER);
    crmf_get_public_value(inPubKey, &challenge->key);
    /* Fall through */
loser:
    if (spki != NULL) {
        SECKEY_DestroySubjectPublicKeyInfo(spki);
    }
    if (encodedRandStr.data != NULL) {
        PORT_Free(encodedRandStr.data);
    }
    if (encodedRandNum != NULL) {
        SECITEM_FreeItem(encodedRandNum, PR_TRUE);
    }
    if (symKey != NULL) {
        PK11_FreeSymKey(symKey);
    }
    return rv;
}