示例#1
0
static SECItem *
crmf_get_iv(CK_MECHANISM_TYPE mechType)
{
    int iv_size = PK11_GetIVLength(mechType);
    SECItem *iv;
    SECStatus rv;

    iv = PORT_ZNew(SECItem);
    if (iv == NULL) {
        return NULL;
    }
    if (iv_size == 0) {
        iv->data = NULL;
        iv->len = 0;
        return iv;
    }
    iv->data = PORT_NewArray(unsigned char, iv_size);
    if (iv->data == NULL) {
        iv->len = 0;
        return iv;
    }
    iv->len = iv_size;
    rv = PK11_GenerateRandom(iv->data, iv->len);
    if (rv != SECSuccess) {
        PORT_Free(iv->data);
        iv->data = NULL;
        iv->len = 0;
    }
    return iv;
}
/*
 * Generate an IV for the given mechanism 
 */
static SECStatus
pk11_GenIV(CK_MECHANISM_TYPE type, SECItem *iv) {
    int iv_size = PK11_GetIVLength(type);
    SECStatus rv;

    iv->len = iv_size;
    if (iv_size == 0) { 
	iv->data = NULL;
	return SECSuccess;
    }

    iv->data = (unsigned char *) PORT_Alloc(iv_size);
    if (iv->data == NULL) {
	iv->len = 0;
	return SECFailure;
    }

    rv = PK11_GenerateRandom(iv->data,iv->len);
    if (rv != SECSuccess) {
	PORT_Free(iv->data);
	iv->data = NULL; iv->len = 0;
	return SECFailure;
    }
    return SECSuccess;
}
CK_RV
PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism, 
				      CK_MECHANISM_PTR pCryptoMechanism,
				      SECItem *pbe_pwd, PRBool faulty3DES)
{
    int iv_len = 0;
    CK_PBE_PARAMS_PTR pPBEparams;
    CK_RC2_CBC_PARAMS_PTR rc2_params;
    CK_ULONG rc2_key_len;

    if((pPBEMechanism == CK_NULL_PTR) || (pCryptoMechanism == CK_NULL_PTR)) {
	return CKR_HOST_MEMORY;
    }

    /* pkcs5 v2 cannot be supported by this interface.
     * use PK11_GetPBECryptoMechanism instead.
     */
    if ((pPBEMechanism->mechanism == CKM_INVALID_MECHANISM) || 
	(pPBEMechanism->mechanism == CKM_PKCS5_PBKD2)) {
	return CKR_MECHANISM_INVALID;
    }

    pPBEparams = (CK_PBE_PARAMS_PTR)pPBEMechanism->pParameter;
    iv_len = PK11_GetIVLength(pPBEMechanism->mechanism);

    if (iv_len) {
	if (pk11_isAllZero(pPBEparams->pInitVector,iv_len)) {
	    SECItem param;
	    PK11SymKey *symKey;
	    PK11SlotInfo *intSlot = PK11_GetInternalSlot();

	    if (intSlot == NULL) {
		return CKR_DEVICE_ERROR;
	    }

	    param.data = pPBEMechanism->pParameter;
	    param.len = pPBEMechanism->ulParameterLen;

	    symKey = PK11_RawPBEKeyGen(intSlot,
		pPBEMechanism->mechanism, &param, pbe_pwd, faulty3DES, NULL);
	    PK11_FreeSlot(intSlot);
	    if (symKey== NULL) {
		return CKR_DEVICE_ERROR; /* sigh */
	    }
	    PK11_FreeSymKey(symKey);
	}
    }

    switch(pPBEMechanism->mechanism) {
	case CKM_PBE_MD2_DES_CBC:
	case CKM_PBE_MD5_DES_CBC:
	case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
	    pCryptoMechanism->mechanism = CKM_DES_CBC;
	    goto have_crypto_mechanism;
	case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
	case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
	case CKM_PBE_SHA1_DES3_EDE_CBC:
	case CKM_PBE_SHA1_DES2_EDE_CBC:
	    pCryptoMechanism->mechanism = CKM_DES3_CBC;
have_crypto_mechanism:
	    pCryptoMechanism->pParameter = PORT_Alloc(iv_len);
	    pCryptoMechanism->ulParameterLen = (CK_ULONG)iv_len;
	    if(pCryptoMechanism->pParameter == NULL) {
		return CKR_HOST_MEMORY;
	    }
	    PORT_Memcpy((unsigned char *)(pCryptoMechanism->pParameter),
			(unsigned char *)(pPBEparams->pInitVector),
			iv_len);
	    break;
	case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:
	case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:
	case CKM_PBE_SHA1_RC4_40:
	case CKM_PBE_SHA1_RC4_128:
	    pCryptoMechanism->mechanism = CKM_RC4;
	    pCryptoMechanism->ulParameterLen = 0;
	    pCryptoMechanism->pParameter = CK_NULL_PTR;
	    break;
	case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
	case CKM_PBE_SHA1_RC2_40_CBC:
	    rc2_key_len = 40;
	    goto have_key_len;
	case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:
	    rc2_key_len = 128;
have_key_len:
	    pCryptoMechanism->mechanism = CKM_RC2_CBC;
	    pCryptoMechanism->ulParameterLen = (CK_ULONG)
						sizeof(CK_RC2_CBC_PARAMS);
	    pCryptoMechanism->pParameter = (CK_RC2_CBC_PARAMS_PTR)
				PORT_ZAlloc(sizeof(CK_RC2_CBC_PARAMS));
	    if(pCryptoMechanism->pParameter == NULL) {
		return CKR_HOST_MEMORY;
	    }
	    rc2_params = (CK_RC2_CBC_PARAMS_PTR)pCryptoMechanism->pParameter;
	    PORT_Memcpy((unsigned char *)rc2_params->iv,
	    		(unsigned char *)pPBEparams->pInitVector,
	    		iv_len);
	    rc2_params->ulEffectiveBits = rc2_key_len;
	    break;
	default:
	    return CKR_MECHANISM_INVALID;
    }

    return CKR_OK;
}
示例#4
0
/**
 * @brief Create a key from the given passphrase. By default, the PBKDF2
 *        algorithm is used to generate the key from the passphrase. It is expected
 *        that the same pass phrase will generate the same key, regardless of the
 *        backend crypto platform used. The key is cleaned up when the context
 *        is cleaned, and may be reused with multiple encryption or decryption
 *        operations.
 * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
 *       *key is not NULL, *key must point at a previously created structure.
 * @param key The key returned, see note.
 * @param ivSize The size of the initialisation vector will be returned, based
 *               on whether an IV is relevant for this type of crypto.
 * @param pass The passphrase to use.
 * @param passLen The passphrase length in bytes
 * @param salt The salt to use.
 * @param saltLen The salt length in bytes
 * @param type 3DES_192, AES_128, AES_192, AES_256.
 * @param mode Electronic Code Book / Cipher Block Chaining.
 * @param doPad Pad if necessary.
 * @param iterations Iteration count
 * @param f The context to use.
 * @param p The pool to use.
 * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
 *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
 *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
 *         not known. APR_EPADDING if padding was requested but is not supported.
 *         APR_ENOTIMPL if not implemented.
 */
static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
        const char *pass, apr_size_t passLen, const unsigned char * salt,
        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
        const apr_crypto_block_key_mode_e mode, const int doPad,
        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
{
    apr_status_t rv = APR_SUCCESS;
    PK11SlotInfo * slot;
    SECItem passItem;
    SECItem saltItem;
    SECAlgorithmID *algid;
    void *wincx = NULL; /* what is wincx? */
    apr_crypto_key_t *key = *k;

    if (!key) {
        *k = key = apr_array_push(f->keys);
    }
    if (!key) {
        return APR_ENOMEM;
    }

    key->f = f;
    key->provider = f->provider;

    /* decide on what cipher mechanism we will be using */
    switch (type) {

    case (APR_KEY_3DES_192):
        if (APR_MODE_CBC == mode) {
            key->cipherOid = SEC_OID_DES_EDE3_CBC;
        }
        else if (APR_MODE_ECB == mode) {
            return APR_ENOCIPHER;
            /* No OID for CKM_DES3_ECB; */
        }
        break;
    case (APR_KEY_AES_128):
        if (APR_MODE_CBC == mode) {
            key->cipherOid = SEC_OID_AES_128_CBC;
        }
        else {
            key->cipherOid = SEC_OID_AES_128_ECB;
        }
        break;
    case (APR_KEY_AES_192):
        if (APR_MODE_CBC == mode) {
            key->cipherOid = SEC_OID_AES_192_CBC;
        }
        else {
            key->cipherOid = SEC_OID_AES_192_ECB;
        }
        break;
    case (APR_KEY_AES_256):
        if (APR_MODE_CBC == mode) {
            key->cipherOid = SEC_OID_AES_256_CBC;
        }
        else {
            key->cipherOid = SEC_OID_AES_256_ECB;
        }
        break;
    default:
        /* unknown key type, give up */
        return APR_EKEYTYPE;
    }

    /* AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD */
    key->cipherMech = PK11_AlgtagToMechanism(key->cipherOid);
    if (key->cipherMech == CKM_INVALID_MECHANISM) {
        return APR_ENOCIPHER;
    }
    if (doPad) {
        CK_MECHANISM_TYPE paddedMech;
        paddedMech = PK11_GetPadMechanism(key->cipherMech);
        if (CKM_INVALID_MECHANISM == paddedMech || key->cipherMech
                == paddedMech) {
            return APR_EPADDING;
        }
        key->cipherMech = paddedMech;
    }

    /* Turn the raw passphrase and salt into SECItems */
    passItem.data = (unsigned char*) pass;
    passItem.len = passLen;
    saltItem.data = (unsigned char*) salt;
    saltItem.len = saltLen;

    /* generate the key */
    /* pbeAlg and cipherAlg are the same. NSS decides the keylength. */
    algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
            SEC_OID_HMAC_SHA1, 0, iterations, &saltItem);
    if (algid) {
        slot = PK11_GetBestSlot(key->cipherMech, wincx);
        if (slot) {
            key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
                    wincx);
            PK11_FreeSlot(slot);
        }
        SECOID_DestroyAlgorithmID(algid, PR_TRUE);
    }

    /* sanity check? */
    if (!key->symKey) {
        PRErrorCode perr = PORT_GetError();
        if (perr) {
            f->result->rc = perr;
            f->result->msg = PR_ErrorToName(perr);
            rv = APR_ENOKEY;
        }
    }

    key->ivSize = PK11_GetIVLength(key->cipherMech);
    if (ivSize) {
        *ivSize = key->ivSize;
    }

    return rv;
}