1 /* Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
3 /** \file openssl.c Openssl-based encryption/decryption routines. */
7 #include <sys/socket.h>
8 #include <openssl/rand.h>
9 #include <openssl/err.h>
10 #include <openssl/pem.h>
11 #include <openssl/sha.h>
12 #include <openssl/bn.h>
13 #include <openssl/aes.h>
19 #include "crypt_backend.h"
20 #include "portable_io.h"
22 struct asymmetric_key
{
26 void get_random_bytes_or_die(unsigned char *buf
, int num
)
30 /* RAND_bytes() returns 1 on success, 0 otherwise. */
31 if (RAND_bytes(buf
, num
) == 1)
33 err
= ERR_get_error();
34 PARA_EMERG_LOG("%s\n", ERR_reason_error_string(err
));
39 * Read 64 bytes from /dev/urandom and add them to the SSL PRNG. Seed the PRNG
40 * used by random(3) with a random seed obtained from SSL. If /dev/urandom is
41 * not readable, the function calls exit().
43 * \sa RAND_load_file(3), \ref get_random_bytes_or_die(), srandom(3),
44 * random(3), \ref para_random().
48 int seed
, ret
= RAND_load_file("/dev/urandom", 64);
51 PARA_EMERG_LOG("could not seed PRNG (ret = %d)\n", ret
);
54 get_random_bytes_or_die((unsigned char *)&seed
, sizeof(seed
));
58 void crypt_shutdown(void)
60 CRYPTO_cleanup_all_ex_data();
63 static int get_private_key(const char *path
, RSA
**rsa
)
66 BIO
*bio
= BIO_new(BIO_s_file());
70 return -E_PRIVATE_KEY
;
71 if (BIO_read_filename(bio
, path
) <= 0)
73 pkey
= PEM_read_bio_PrivateKey(bio
, NULL
, NULL
, NULL
);
76 *rsa
= EVP_PKEY_get1_RSA(pkey
);
80 return *rsa
? RSA_size(*rsa
) : -E_PRIVATE_KEY
;
84 * The public key loading functions below were inspired by corresponding code
85 * of openssh-5.2p1, Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo,
86 * Finland. However, not much of the original code remains.
89 static int read_bignum(const unsigned char *buf
, size_t len
, BIGNUM
**result
)
91 const unsigned char *p
= buf
, *end
= buf
+ len
;
99 bnsize
= read_u32_be(p
);
100 PARA_DEBUG_LOG("bnsize: %u\n", bnsize
);
104 if (p
+ bnsize
> end
)
108 bn
= BN_bin2bn(p
, bnsize
, NULL
);
115 static int read_rsa_bignums(const unsigned char *blob
, int blen
, RSA
**result
)
120 const unsigned char *p
= blob
, *end
= blob
+ blen
;
125 ret
= read_bignum(p
, end
- p
, &e
);
129 ret
= read_bignum(p
, end
- p
, &n
);
132 #ifdef HAVE_RSA_SET0_KEY
133 RSA_set0_key(rsa
, n
, e
, NULL
);
147 int apc_get_pubkey(const char *key_file
, struct asymmetric_key
**result
)
152 struct asymmetric_key
*key
= para_malloc(sizeof(*key
));
154 ret
= decode_ssh_key(key_file
, &blob
, &decoded_size
);
157 ret
= read_rsa_bignums(blob
+ ret
, decoded_size
- ret
, &key
->rsa
);
160 ret
= RSA_size(key
->rsa
);
169 PARA_ERROR_LOG("can not load key %s\n", key_file
);
174 void apc_free_pubkey(struct asymmetric_key
*key
)
182 int apc_priv_decrypt(const char *key_file
, unsigned char *outbuf
,
183 unsigned char *inbuf
, int inlen
)
185 struct asymmetric_key
*priv
;
188 ret
= check_private_key_file(key_file
);
193 priv
= para_malloc(sizeof(*priv
));
194 ret
= get_private_key(key_file
, &priv
->rsa
);
200 * RSA is vulnerable to timing attacks. Generate a random blinding
201 * factor to protect against this kind of attack.
204 if (RSA_blinding_on(priv
->rsa
, NULL
) == 0)
206 ret
= RSA_private_decrypt(inlen
, inbuf
, outbuf
, priv
->rsa
,
207 RSA_PKCS1_OAEP_PADDING
);
208 RSA_blinding_off(priv
->rsa
);
217 int apc_pub_encrypt(struct asymmetric_key
*pub
, unsigned char *inbuf
,
218 unsigned len
, unsigned char *outbuf
)
220 int ret
, flen
= len
; /* RSA_public_encrypt expects a signed int */
224 ret
= RSA_public_encrypt(flen
, inbuf
, outbuf
, pub
->rsa
,
225 RSA_PKCS1_OAEP_PADDING
);
226 return ret
< 0? -E_ENCRYPT
: ret
;
229 struct stream_cipher
{
233 struct stream_cipher
*sc_new(const unsigned char *data
, int len
)
235 struct stream_cipher
*sc
= para_malloc(sizeof(*sc
));
237 assert(len
>= 2 * AES_CRT128_BLOCK_SIZE
);
238 sc
->aes
= EVP_CIPHER_CTX_new();
239 EVP_EncryptInit_ex(sc
->aes
, EVP_aes_128_ctr(), NULL
, data
,
240 data
+ AES_CRT128_BLOCK_SIZE
);
244 void sc_free(struct stream_cipher
*sc
)
248 EVP_CIPHER_CTX_free(sc
->aes
);
252 static void aes_ctr128_crypt(EVP_CIPHER_CTX
*ctx
, struct iovec
*src
,
255 int ret
, inlen
= src
->iov_len
, outlen
, tmplen
;
257 *dst
= (typeof(*dst
)) {
258 /* Add one for the terminating zero byte. */
259 .iov_base
= para_malloc(inlen
+ 1),
262 ret
= EVP_EncryptUpdate(ctx
, dst
->iov_base
, &outlen
, src
->iov_base
, inlen
);
264 ret
= EVP_EncryptFinal_ex(ctx
, dst
->iov_base
+ outlen
, &tmplen
);
267 ((char *)dst
->iov_base
)[outlen
] = '\0';
268 dst
->iov_len
= outlen
;
271 void sc_crypt(struct stream_cipher
*sc
, struct iovec
*src
, struct iovec
*dst
)
273 return aes_ctr128_crypt(sc
->aes
, src
, dst
);
276 void hash_function(const char *data
, unsigned long len
, unsigned char *hash
)
280 SHA1_Update(&c
, data
, len
);
281 SHA1_Final(hash
, &c
);