dcrypt-openssl.c revision 0eaf77d8c22c542d5bd474bf1460d811876629d7
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen key format documentation:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen =========================
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen algo id = openssl NID
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen enctype = 0 = none, 1 = ecdhe, 2 = password
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen key id = sha256(hex encoded public point)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen 1<tab>algo id<tab>public point
66fbbac231b0385273b11f9b4c43ad252330dea5Timo Sirainen - enctype none
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen 1<tab>algo id<tab>0<tab>private point<tab>key id
66fbbac231b0385273b11f9b4c43ad252330dea5Timo Sirainen - enctype ecdh (algorithm AES-256-CTR, key = SHA256(shared secret), IV = \0\0\0...)
66fbbac231b0385273b11f9b4c43ad252330dea5Timo Sirainen 1<tab>algo id<tab>1<tab>private point<tab>ephemeral public key<tab>encryption key id<tab>key id
66fbbac231b0385273b11f9b4c43ad252330dea5Timo Sirainen - enctype password (algorithm AES-256-CTR, key = PBKDF2(SHA1, 16, password, salt), IV = \0\0\0...)
66fbbac231b0385273b11f9b4c43ad252330dea5Timo Sirainen 1<tab>algo id<tab>2<tab>private point<tab>salt<tab>key id
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen algo oid = ASN1 OID of key algorithm (RSA or EC curve)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen enctype = 0 = none, 1 = ecdhe, 2 = password
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen key id = SHA256(i2d_PUBKEY)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen 2<tab>HEX(i2d_PUBKEY)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen - enctype none
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen 2<tab>key algo oid<tab>0<tab>(RSA = i2d_PrivateKey, EC=Private Point)<tab>key id
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen - enctype ecdh, key,iv = PBKDF2(hash algo, rounds, shared secret, salt)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen 2<tab>key algo oid<tab>1<tab>symmetric algo name<tab>salt<tab>hash algo<tab>rounds<tab>E(RSA = i2d_PrivateKey, EC=Private Point)<tab>ephemeral public key<tab>encryption key id<tab>key id
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen - enctype password, key,iv = PBKDF2(hash algo, rounds, password, salt)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen 2<tab>key algo oid<tab>1<tab>symmetric algo name<tab>salt<tab>hash algo<tab>rounds<tab>E(RSA = i2d_PrivateKey, EC=Private Point)<tab>key id
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned char *key;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned char *iv;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned char *aad;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned char *tag;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned char *key;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_public_key_id(struct dcrypt_public_key *key, const char *algorithm, buffer_t *result, const char **error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_public_key_id_old(struct dcrypt_public_key *key, buffer_t *result, const char **error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_private_key_id(struct dcrypt_private_key *key, const char *algorithm, buffer_t *result, const char **error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_private_key_id_old(struct dcrypt_private_key *key, buffer_t *result, const char **error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_private_to_public_key(struct dcrypt_private_key *priv_key, struct dcrypt_public_key **pub_key_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_free_private_key(struct dcrypt_private_key **key);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_free_public_key(struct dcrypt_public_key **key);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_rsa_decrypt(struct dcrypt_private_key *key, const unsigned char *data, size_t data_len, buffer_t *result, const char **error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_error(const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if(error_r == NULL) return FALSE; /* caller is not really interested */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen *error_r = t_strdup_printf("%s", ERR_error_string(ec, NULL));
e5c28185478ecab60d0dbd78f9daaab113d5c060Timo Sirainenbool dcrypt_openssl_initialize(const struct dcrypt_settings *set, const char **error_r)
e5c28185478ecab60d0dbd78f9daaab113d5c060Timo Sirainen if (set->crypto_device != NULL && set->crypto_device[0] != '\0') {
e5c28185478ecab60d0dbd78f9daaab113d5c060Timo Sirainen if (dovecot_openssl_common_global_set_engine(set->crypto_device, error_r) <= 0)
ba8a3fbee3f8fca8e481ba929bce6b78296a7820Timo Sirainen/* legacy function for old formats that generates
ba8a3fbee3f8fca8e481ba929bce6b78296a7820Timo Sirainen hex encoded point from EC public key
ba8a3fbee3f8fca8e481ba929bce6b78296a7820Timo Sirainenchar *ec_key_get_pub_point_hex(const EC_KEY *key)
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen return EC_POINT_point2hex(g, p, POINT_CONVERSION_COMPRESSED, NULL);
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainenbool dcrypt_openssl_ctx_sym_create(const char *algorithm, enum dcrypt_sym_mode mode, struct dcrypt_context_symmetric **ctx_r, const char **error_r)
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen *error_r = t_strdup_printf("Invalid cipher %s", algorithm);
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen /* allocate context */
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen pool = pool_alloconly_create("dcrypt openssl", 1024);
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen ctx = p_new(pool, struct dcrypt_context_symmetric, 1);
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen ctx->mode =( mode == DCRYPT_MODE_ENCRYPT ? 1 : 0 );
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainenvoid dcrypt_openssl_ctx_sym_destroy(struct dcrypt_context_symmetric **ctx)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if ((*ctx)->ctx != NULL) EVP_CIPHER_CTX_free((*ctx)->ctx);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_ctx_sym_set_key(struct dcrypt_context_symmetric *ctx, const unsigned char *key, size_t key_len)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if(ctx->key != NULL) p_free(ctx->pool, ctx->key);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->key = p_malloc(ctx->pool, EVP_CIPHER_key_length(ctx->cipher));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen memcpy(ctx->key, key, I_MIN(key_len,(size_t)EVP_CIPHER_key_length(ctx->cipher)));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_ctx_sym_set_iv(struct dcrypt_context_symmetric *ctx, const unsigned char *iv, size_t iv_len)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if(ctx->iv != NULL) p_free(ctx->pool, ctx->iv);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->iv = p_malloc(ctx->pool, EVP_CIPHER_iv_length(ctx->cipher));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen memcpy(ctx->iv, iv, I_MIN(iv_len,(size_t)EVP_CIPHER_iv_length(ctx->cipher)));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_ctx_sym_set_key_iv_random(struct dcrypt_context_symmetric *ctx)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if(ctx->key != NULL) p_free(ctx->pool, ctx->key);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if(ctx->iv != NULL) p_free(ctx->pool, ctx->iv);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->key = p_malloc(ctx->pool, EVP_CIPHER_key_length(ctx->cipher));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen random_fill(ctx->key, EVP_CIPHER_key_length(ctx->cipher));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->iv = p_malloc(ctx->pool, EVP_CIPHER_iv_length(ctx->cipher));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen random_fill(ctx->iv, EVP_CIPHER_iv_length(ctx->cipher));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_ctx_sym_set_padding(struct dcrypt_context_symmetric *ctx, bool padding)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_sym_get_key(struct dcrypt_context_symmetric *ctx, buffer_t *key)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen buffer_append(key, ctx->key, EVP_CIPHER_key_length(ctx->cipher));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_sym_get_iv(struct dcrypt_context_symmetric *ctx, buffer_t *iv)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen buffer_append(iv, ctx->iv, EVP_CIPHER_iv_length(ctx->cipher));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_ctx_sym_set_aad(struct dcrypt_context_symmetric *ctx, const unsigned char *aad, size_t aad_len)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (ctx->aad != NULL) p_free(ctx->pool, ctx->aad);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* allow empty aad */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->aad = p_malloc(ctx->pool, I_MAX(1,aad_len));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_sym_get_aad(struct dcrypt_context_symmetric *ctx, buffer_t *aad)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_ctx_sym_set_tag(struct dcrypt_context_symmetric *ctx, const unsigned char *tag, size_t tag_len)
417d2a64eba7d8c395b6c8a18d845f7ff2471637Timo Sirainen if (ctx->tag != NULL) p_free(ctx->pool, ctx->tag);
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen /* unlike aad, tag cannot be empty */
e7a81e78fb5d8078d32ec05257f75095b28eb9e8Timo Sirainenbool dcrypt_openssl_ctx_sym_get_tag(struct dcrypt_context_symmetric *ctx, buffer_t *tag)
417d2a64eba7d8c395b6c8a18d845f7ff2471637Timo Sirainenunsigned int dcrypt_openssl_ctx_sym_get_key_length(struct dcrypt_context_symmetric *ctx)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenunsigned int dcrypt_openssl_ctx_sym_get_iv_length(struct dcrypt_context_symmetric *ctx)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenunsigned int dcrypt_openssl_ctx_sym_get_block_size(struct dcrypt_context_symmetric *ctx)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_sym_init(struct dcrypt_context_symmetric *ctx, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ec = EVP_CipherInit_ex(ctx->ctx, ctx->cipher, NULL, ctx->key, ctx->iv, ctx->mode);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (ec != 1) return dcrypt_openssl_error(error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen EVP_CIPHER_CTX_set_padding(ctx->ctx, ctx->padding);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (ctx->aad != NULL) ec = EVP_CipherUpdate(ctx->ctx, NULL, &len, ctx->aad, ctx->aad_len);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (ec != 1) return dcrypt_openssl_error(error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_sym_update(struct dcrypt_context_symmetric *ctx, const unsigned char *data, size_t data_len, buffer_t *result, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const size_t block_size = (size_t)EVP_CIPHER_block_size(ctx->cipher);
358f356749078ed2ae69fc48ced375761c877b61Timo Sirainen unsigned char *buf;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* From `man 3 evp_cipherupdate`:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen EVP_EncryptUpdate() encrypts inl bytes from the buffer in and writes
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen the encrypted version to out. This function can be called multiple
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen times to encrypt successive blocks of data. The amount of data written
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen depends on the block alignment of the encrypted data: as a result the
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen amount of data written may be anything from zero bytes to
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen (inl + cipher_block_size - 1) so out should contain sufficient room.
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen The actual number of bytes written is placed in outl.
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen buf = buffer_append_space_unsafe(result, data_len + block_size);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen buffer_set_used_size(result, buf_used + outl);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_sym_final(struct dcrypt_context_symmetric *ctx, buffer_t *result, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const size_t block_size = (size_t)EVP_CIPHER_block_size(ctx->cipher);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned char *buf;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* From `man 3 evp_cipherupdate`:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen the "final" data, that is any data that remains in a partial block. It
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen uses standard block padding (aka PKCS padding). The encrypted final data
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen is written to out which should have sufficient space for one cipher
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen block. The number of bytes written is placed in outl. After this
a37c2c1ad645b6d8ea73e6d38695efdde4f3f928Timo Sirainen function is called the encryption operation is finished and no further
a37c2c1ad645b6d8ea73e6d38695efdde4f3f928Timo Sirainen calls to EVP_EncryptUpdate() should be made.
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen buf = buffer_append_space_unsafe(result, block_size);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* when **DECRYPTING** set expected tag */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ec = EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_TAG, ctx->tag_len, ctx->tag);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ec = EVP_CipherFinal_ex(ctx->ctx, buf, &outl);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen buffer_set_used_size(result, buf_used + outl);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* when **ENCRYPTING** recover tag */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* tag should be NULL here */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* openssl claims taglen is always 16, go figure .. */
a37c2c1ad645b6d8ea73e6d38695efdde4f3f928Timo Sirainen ctx->tag = p_malloc(ctx->pool, EVP_GCM_TLS_TAG_LEN);
a37c2c1ad645b6d8ea73e6d38695efdde4f3f928Timo Sirainen ec = EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN, ctx->tag);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen else if (ec < 0) dcrypt_openssl_error(error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_hmac_create(const char *algorithm, struct dcrypt_context_hmac **ctx_r, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen *error_r = t_strdup_printf("Invalid digest %s", algorithm);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* allocate context */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen pool = pool_alloconly_create("dcrypt openssl", 1024);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx = p_new(pool, struct dcrypt_context_hmac, 1);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_ctx_hmac_destroy(struct dcrypt_context_hmac **ctx)
5ce40a7370a19a98caeca5d2e27b3d6c77c90ea9Timo Sirainenvoid dcrypt_openssl_ctx_hmac_set_key(struct dcrypt_context_hmac *ctx, const unsigned char *key, size_t key_len)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if(ctx->key != NULL) p_free(ctx->pool, ctx->key);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->klen = I_MIN(key_len, HMAC_MAX_MD_CBLOCK);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_hmac_get_key(struct dcrypt_context_hmac *ctx, buffer_t *key)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid dcrypt_openssl_ctx_hmac_set_key_random(struct dcrypt_context_hmac *ctx)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenunsigned int dcrypt_openssl_ctx_hmac_get_digest_length(struct dcrypt_context_hmac *ctx)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_hmac_init(struct dcrypt_context_hmac *ctx, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ec = HMAC_Init_ex(ctx->ctx, ctx->key, ctx->klen, ctx->md, NULL);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ec = HMAC_Init_ex(&(ctx->ctx), ctx->key, ctx->klen, ctx->md, NULL);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (ec != 1) return dcrypt_openssl_error(error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_hmac_update(struct dcrypt_context_hmac *ctx, const unsigned char *data, size_t data_len, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ec = HMAC_Update(&(ctx->ctx), data, data_len);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (ec != 1) return dcrypt_openssl_error(error_r);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ctx_hmac_final(struct dcrypt_context_hmac *ctx, buffer_t *result, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned int outl;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_generate_ec_key(int nid, EVP_PKEY **key, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* generate parameters for EC */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) < 1 ||
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* generate key from parameters */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen EC_KEY_set_asn1_flag(EVP_PKEY_get0_EC_KEY((*key)), OPENSSL_EC_NAMED_CURVE);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen EC_KEY_set_conv_form(EVP_PKEY_get0_EC_KEY((*key)), POINT_CONVERSION_COMPRESSED);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_generate_rsa_key(int bits, EVP_PKEY **key, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) < 1 ||
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen return ec == 0;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ecdh_derive_secret_local(struct dcrypt_private_key *local_key, buffer_t *R, buffer_t *S, const char **error_r)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const EC_GROUP *grp = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(local));
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* convert ephemeral key data EC point */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (EC_POINT_oct2point(grp, pub, R->data, R->used, bn_ctx) != 1)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* convert point to public key */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen EC_KEY_set_conv_form(ec_key, POINT_CONVERSION_COMPRESSED);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* make sure it looks like a valid key */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(local, NULL);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* initialize derivation */
ec1823d289727d53fc74073e6cdda61d64fc0761Timo Sirainen /* have to do it twice to get the data length */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenbool dcrypt_openssl_ecdh_derive_secret_peer(struct dcrypt_public_key *peer_key, buffer_t *R, buffer_t *S, const char **error_r)
return FALSE;
return TRUE;
bool dcrypt_openssl_pbkdf2(const unsigned char *password, size_t password_len, const unsigned char *salt, size_t salt_len,
const char *hash, unsigned int rounds, buffer_t *result, unsigned int result_len, const char **error_r)
int ret;
return FALSE;
return TRUE;
bool dcrypt_openssl_generate_keypair(struct dcrypt_keypair *pair_r, enum dcrypt_key_type kind, unsigned int bits, const char *curve, const char **error_r)
return TRUE;
return FALSE;
return TRUE;
return FALSE;
bool dcrypt_openssl_decrypt_point_v1(buffer_t *data, buffer_t *key, BIGNUM **point_r, const char **error_r)
return FALSE;
dcrypt_openssl_ctx_sym_set_iv(dctx, (const unsigned char*)"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16);
return FALSE;
return TRUE;
bool res;
return FALSE;
return res;
return FALSE;
const char **error_r)
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
bool res;
return FALSE;
if (!res) {
return FALSE;
dcrypt_openssl_ctx_sym_set_iv(dctx, kd+dcrypt_openssl_ctx_sym_get_key_length(dctx), dcrypt_openssl_ctx_sym_get_iv_length(dctx));
return res;
const char **error_r)
int enctype;
return FALSE;
return FALSE;
return FALSE;
unsigned int rounds;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
unsigned int rounds;
return FALSE;
return FALSE;
return FALSE;
int ec;
return FALSE;
return TRUE;
const char **error_r)
bool ret;
return ret;
int nid;
const unsigned char *ptr;
int ec = 0;
bool dcrypt_openssl_encrypt_private_key_dovecot(buffer_t *key, int enctype, const char *cipher, const char *password,
bool res;
unsigned char *ptr;
return FALSE;
return FALSE;
i_unreached();
return FALSE;
return res;
bool dcrypt_openssl_store_private_key_dovecot(struct dcrypt_private_key *key, const char *cipher, buffer_t *destination,
int enctype = 0;
return FALSE;
unsigned char *ptr;
unsigned char *ptr;
i_unreached();
if (enctype > 0) {
if (!dcrypt_openssl_encrypt_private_key_dovecot(buf, enctype, cipher2, password, enc_key, destination, error_r)) {
return FALSE;
if (!res) {
return FALSE;
return TRUE;
bool dcrypt_openssl_store_public_key_dovecot(struct dcrypt_public_key *key, buffer_t *destination, const char **error_r)
return TRUE;
bool dcrypt_openssl_load_private_key(struct dcrypt_private_key **key_r, enum dcrypt_key_format format,
const char **error_r)
return TRUE;
bool dcrypt_openssl_load_public_key(struct dcrypt_public_key **key_r, enum dcrypt_key_format format,
return FALSE;
return TRUE;
bool dcrypt_openssl_store_private_key(struct dcrypt_private_key *key, enum dcrypt_key_format format,
const char **error_r)
int ec;
bool ret;
ret = dcrypt_openssl_store_private_key_dovecot(key, cipher, destination, password, enc_key, error_r);
return ret;
return FALSE;
long bs;
char *buf;
return TRUE;
bool dcrypt_openssl_store_public_key(struct dcrypt_public_key *key, enum dcrypt_key_format format, buffer_t *destination, const char **error_r)
int ec;
long bs;
char *buf;
return TRUE;
void dcrypt_openssl_private_to_public_key(struct dcrypt_private_key *priv_key, struct dcrypt_public_key **pub_key_r)
i_unreached();
bool dcrypt_openssl_key_string_get_info(const char *key_data, enum dcrypt_key_format *format_r, enum dcrypt_key_version *version_r,
enum dcrypt_key_kind *kind_r, enum dcrypt_key_encryption_type *encryption_type_r, const char **encryption_key_hash_r,
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
bool dcrypt_openssl_rsa_encrypt(struct dcrypt_public_key *key, const unsigned char *data, size_t data_len, buffer_t *result, const char **error_r)
int ec;
ec = 0;
return ec == 0;
bool dcrypt_openssl_rsa_decrypt(struct dcrypt_private_key *key, const unsigned char *data, size_t data_len, buffer_t *result, const char **error_r)
int ec;
ec = 0;
return ec == 0;
const char *name;
return NULL;
return name;
return FALSE;
return TRUE;
else i_unreached();
else i_unreached();
bool dcrypt_openssl_public_key_id_old(struct dcrypt_public_key *key, buffer_t *result, const char **error_r)
return FALSE;
return TRUE;
bool dcrypt_openssl_private_key_id_old(struct dcrypt_private_key *key, buffer_t *result, const char **error_r)
return FALSE;
return TRUE;
bool dcrypt_openssl_public_key_id_evp(EVP_PKEY *key, const EVP_MD *md, buffer_t *result, const char **error_r)
BIO_vfree(b);
BIO_vfree(b);
return res;
bool dcrypt_openssl_public_key_id(struct dcrypt_public_key *key, const char *algorithm, buffer_t *result, const char **error_r)
return FALSE;
bool dcrypt_openssl_private_key_id(struct dcrypt_private_key *key, const char *algorithm, buffer_t *result, const char **error_r)
return FALSE;
void dcrypt_openssl_deinit(void)