Exemplo n.º 1
0
static int
parse_pkcs8_private_key(hx509_context context, const char *fn,
			struct hx509_collector *c,
			const hx509_pem_header *headers,
			const void *data, size_t length,
			const AlgorithmIdentifier *ai)
{
    PKCS8PrivateKeyInfo ki;
    heim_octet_string keydata;

    int ret;

    ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL);
    if (ret)
	return ret;

    keydata.data = rk_UNCONST(data);
    keydata.length = length;

    ret = _hx509_collector_private_key_add(context,
					   c,
					   &ki.privateKeyAlgorithm,
					   NULL,
					   &ki.privateKey,
					   &keydata);
    free_PKCS8PrivateKeyInfo(&ki);
    return ret;
}
Exemplo n.º 2
0
static int
keyBag_parser(hx509_context context,
	      struct hx509_collector *c,
	      const void *data, size_t length,
	      const PKCS12_Attributes *attrs)
{
    const PKCS12_Attribute *attr;
    PKCS8PrivateKeyInfo ki;
    const heim_octet_string *os = NULL;
    int ret;

    attr = find_attribute(attrs, &asn1_oid_id_pkcs_9_at_localKeyId);
    if (attr)
	os = &attr->attrValues;

    ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL);
    if (ret)
	return ret;

    _hx509_collector_private_key_add(context,
				     c,
				     &ki.privateKeyAlgorithm,
				     NULL,
				     &ki.privateKey,
				     os);
    free_PKCS8PrivateKeyInfo(&ki);
    return 0;
}
Exemplo n.º 3
0
static int
try_decrypt(hx509_context context,
	    struct hx509_collector *collector,
	    const AlgorithmIdentifier *alg,
	    const EVP_CIPHER *c,
	    const void *ivdata,
	    const void *password,
	    size_t passwordlen,
	    const void *cipher,
	    size_t len)
{
    heim_octet_string clear;
    size_t keylen;
    void *key;
    int ret;

    keylen = EVP_CIPHER_key_length(c);

    key = malloc(keylen);
    if (key == NULL) {
	hx509_clear_error_string(context);
	return ENOMEM;
    }

    ret = EVP_BytesToKey(c, EVP_md5(), ivdata,
			 password, passwordlen,
			 1, key, NULL);
    if (ret <= 0) {
	hx509_set_error_string(context, 0, HX509_CRYPTO_INTERNAL_ERROR,
			       "Failed to do string2key for private key");
	return HX509_CRYPTO_INTERNAL_ERROR;
    }

    clear.data = malloc(len);
    if (clear.data == NULL) {
	hx509_set_error_string(context, 0, ENOMEM,
			       "Out of memory to decrypt for private key");
	ret = ENOMEM;
	goto out;
    }
    clear.length = len;

    {
	EVP_CIPHER_CTX ctx;
	EVP_CIPHER_CTX_init(&ctx);
	EVP_CipherInit_ex(&ctx, c, NULL, key, ivdata, 0);
	EVP_Cipher(&ctx, clear.data, cipher, len);
	EVP_CIPHER_CTX_cleanup(&ctx);
    }	

    ret = _hx509_collector_private_key_add(context,
					   collector,
					   alg,
					   NULL,
					   &clear,
					   NULL);

    memset(clear.data, 0, clear.length);
    free(clear.data);
out:
    memset(key, 0, keylen);
    free(key);
    return ret;
}
Exemplo n.º 4
0
static int
parse_rsa_private_key(hx509_context context, const char *fn,
		      struct hx509_collector *c,
		      const hx509_pem_header *headers,
		      const void *data, size_t len)
{
    int ret = 0;
    const char *enc;

    enc = hx509_pem_find_header(headers, "Proc-Type");
    if (enc) {
	const char *dek;
	char *type, *iv;
	ssize_t ssize, size;
	void *ivdata;
	const EVP_CIPHER *cipher;
	const struct _hx509_password *pw;
	hx509_lock lock;
	int i, decrypted = 0;

	lock = _hx509_collector_get_lock(c);
	if (lock == NULL) {
	    hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
				   "Failed to get password for "
				   "password protected file %s", fn);
	    return HX509_ALG_NOT_SUPP;
	}

	if (strcmp(enc, "4,ENCRYPTED") != 0) {
	    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
				   "RSA key encrypted in unknown method %s "
				   "in file",
				   enc, fn);
	    hx509_clear_error_string(context);
	    return HX509_PARSING_KEY_FAILED;
	}

	dek = hx509_pem_find_header(headers, "DEK-Info");
	if (dek == NULL) {
	    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
				   "Encrypted RSA missing DEK-Info");
	    return HX509_PARSING_KEY_FAILED;
	}

	type = strdup(dek);
	if (type == NULL) {
	    hx509_clear_error_string(context);
	    return ENOMEM;
	}

	iv = strchr(type, ',');
	if (iv == NULL) {
	    free(type);
	    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
				   "IV missing");
	    return HX509_PARSING_KEY_FAILED;
	}

	*iv++ = '\0';

	size = strlen(iv);
	ivdata = malloc(size);
	if (ivdata == NULL) {
	    hx509_clear_error_string(context);
	    free(type);
	    return ENOMEM;
	}

	cipher = EVP_get_cipherbyname(type);
	if (cipher == NULL) {
	    free(ivdata);
	    hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
				   "RSA key encrypted with "
				   "unsupported cipher: %s",
				   type);
	    free(type);
	    return HX509_ALG_NOT_SUPP;
	}

#define PKCS5_SALT_LEN 8

	ssize = hex_decode(iv, ivdata, size);
	free(type);
	type = NULL;
	iv = NULL;

	if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) {
	    free(ivdata);
	    hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
				   "Salt have wrong length in RSA key file");
	    return HX509_PARSING_KEY_FAILED;
	}
	
	pw = _hx509_lock_get_passwords(lock);
	if (pw != NULL) {
	    const void *password;
	    size_t passwordlen;

	    for (i = 0; i < pw->len; i++) {
		password = pw->val[i];
		passwordlen = strlen(password);
		
		ret = try_decrypt(context, c, hx509_signature_rsa(),
				  cipher, ivdata, password, passwordlen,
				  data, len);
		if (ret == 0) {
		    decrypted = 1;
		    break;
		}
	    }
	}
	if (!decrypted) {
	    hx509_prompt prompt;
	    char password[128];

	    memset(&prompt, 0, sizeof(prompt));

	    prompt.prompt = "Password for keyfile: ";
	    prompt.type = HX509_PROMPT_TYPE_PASSWORD;
	    prompt.reply.data = password;
	    prompt.reply.length = sizeof(password);

	    ret = hx509_lock_prompt(lock, &prompt);
	    if (ret == 0)
		ret = try_decrypt(context, c, hx509_signature_rsa(),
				  cipher, ivdata, password, strlen(password),
				  data, len);
	    /* XXX add password to lock password collection ? */
	    memset(password, 0, sizeof(password));
	}
	free(ivdata);

    } else {
	heim_octet_string keydata;

	keydata.data = rk_UNCONST(data);
	keydata.length = len;

	ret = _hx509_collector_private_key_add(context,
					       c,
					       hx509_signature_rsa(),
					       NULL,
					       &keydata,
					       NULL);
    }

    return ret;
}
Exemplo n.º 5
0
static int
collect_private_key(hx509_context context,
		    struct p11_module *p, struct p11_slot *slot,
		    CK_SESSION_HANDLE session,
		    CK_OBJECT_HANDLE object,
		    void *ptr, CK_ATTRIBUTE *query, int num_query)
{
    struct hx509_collector *collector = ptr;
    hx509_private_key key;
    heim_octet_string localKeyId;
    int ret;
    RSA *rsa;
    struct p11_rsa *p11rsa;

    localKeyId.data = query[0].pValue;
    localKeyId.length = query[0].ulValueLen;

    ret = _hx509_private_key_init(&key, NULL, NULL);
    if (ret)
	return ret;

    rsa = RSA_new();
    if (rsa == NULL)
	_hx509_abort("out of memory");

    /* 
     * The exponent and modulus should always be present according to
     * the pkcs11 specification, but some smartcards leaves it out,
     * let ignore any failure to fetch it.
     */
    rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS);
    rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT);

    p11rsa = calloc(1, sizeof(*p11rsa));
    if (p11rsa == NULL)
	_hx509_abort("out of memory");

    p11rsa->p = p;
    p11rsa->slot = slot;
    p11rsa->private_key = object;
    
    p->refcount++;
    if (p->refcount == 0)
	_hx509_abort("pkcs11 refcount to high");

    RSA_set_method(rsa, &p11_rsa_pkcs1_method);
    ret = RSA_set_app_data(rsa, p11rsa);
    if (ret != 1)
	_hx509_abort("RSA_set_app_data");

    _hx509_private_key_assign_rsa(key, rsa);

    ret = _hx509_collector_private_key_add(context,
					   collector,
					   hx509_signature_rsa(),
					   key,
					   NULL,
					   &localKeyId);

    if (ret) {
	_hx509_private_key_free(&key);
	return ret;
    }
    return 0;
}