fix
[libexssl.git] / src / libexssl / sslw.c
blobbdb4deb1af2a9800e6618a15b8e996cb3e46c212
1 #include "ssl.h"
3 struct ssl_key {
4 str_t *msg;
5 RSA *rsa;
6 EVP_PKEY *key;
7 };
9 struct ssl_key_pair {
10 str_t *msg;
11 RSA *rsa;
12 EVP_PKEY *pub;
13 EVP_PKEY *priv;
16 const char *ssl_key_msg (ssl_key_t *key) {
17 return key && key->msg ? (const char*)key->msg->ptr : NULL;
20 const char *ssl_keys_msg (ssl_key_pair_t *keys) {
21 return keys && keys->msg ? (const char*)keys->msg->ptr : NULL;
24 int ssl_init () {
25 if (!SSL_library_init()) return -1;
26 SSL_load_error_strings();
27 OpenSSL_add_all_algorithms();
28 RAND_load_file("/dev/urandom", 1024);
29 OpenSSL_add_ssl_algorithms();
30 return 0;
33 void ssl_done () {
34 CRYPTO_cleanup_all_ex_data();
35 ERR_free_strings();
36 #if !(OPENSSL_API_COMPAT < 0x10100000L)
37 ERR_remove_thread_state(0);
38 #endif
39 EVP_cleanup();
42 static str_t *create_error_msg () {
43 str_t *s = stralloc(64, 64);
44 ERR_print_errors_cb(({
45 int fn (const char *str, size_t len, void *u) {
46 str_t **err_str = (str_t**)u;
47 strnadd(err_str, str, len);
48 return (int)(*err_str)->len;
49 } fn;
50 }), &s);
51 return s;
54 static int create_rsa_key (RSA *rsa, int nbits, ssl_key_t *ssl_key) {
55 EVP_PKEY *key = NULL;
56 key = EVP_PKEY_new();
57 if (key && EVP_PKEY_set1_RSA(key, rsa)) {
58 ssl_key->key = key;
59 return 0;
61 ssl_key->msg = create_error_msg();
62 if (key) EVP_PKEY_free(key);
63 return -1;
66 #if OPENSSL_API_COMPAT < 0x10100000L
67 static RSA *gen_keys (int bits, unsigned long e_value) {
68 int i;
69 BN_GENCB *cb = BN_GENCB_new();
70 RSA *rsa = RSA_new();
71 BIGNUM *e = BN_new();
72 if (cb == NULL || rsa == NULL || e == NULL)
73 goto err;
74 for (i = 0; i < (int)sizeof(unsigned long) * 8; i++) {
75 if (e_value & (1UL << i))
76 if (BN_set_bit(e, i) == 0)
77 goto err;
79 BN_GENCB_set_old(cb, NULL, NULL);
80 if (bits < 1024)
81 bits = 1024;
82 if (RSA_generate_key_ex(rsa, bits, e, cb)) {
83 BN_free(e);
84 BN_GENCB_free(cb);
85 return rsa;
87 err:
88 BN_free(e);
89 RSA_free(rsa);
90 OPENSSL_free(cb);
91 return 0;
93 #endif
95 int ssl_gen_keys (int nbits, ssl_key_pair_t *keys) {
96 ssl_key_t pub = { .msg = NULL, .key = NULL, .rsa = NULL },
97 priv = { .msg = NULL, .key = NULL, .rsa = NULL };
98 #if OPENSSL_API_COMPAT < 0x10100000L
99 RSA *rsa = gen_keys(nbits, RSA_F4);
100 #else
101 RSA *rsa = RSA_generate_key(nbits, RSA_F4, NULL, NULL);
102 #endif
103 if (!rsa) {
104 keys->msg = create_error_msg();
105 return -1;
107 if (-1 == create_rsa_key(rsa, nbits, &priv)) {
108 RSA_free(rsa);
109 keys->msg = priv.msg;
110 return -1;
112 if (-1 == create_rsa_key(rsa, nbits, &pub)) {
113 RSA_free(rsa);
114 EVP_PKEY_free(priv.key);
115 priv.key = NULL;
116 keys->msg = pub.msg;
117 return -1;
119 if (0 >= RSA_check_key(rsa)) {
120 RSA_free(rsa);
121 EVP_PKEY_free(priv.key);
122 EVP_PKEY_free(pub.key);
123 keys->msg = create_error_msg();
124 return -1;
126 keys->rsa = rsa;
127 keys->priv = priv.key;
128 keys->pub = pub.key;
129 return 0;
132 int ssl_gen_keys_fp (int nbits, FILE *fp_priv, FILE *fp_pub, const char *passwd, ssl_key_pair_t *keys) {
133 int ret;
134 if (-1 == (ret = ssl_gen_keys(nbits, keys))) return -1;
135 if (!PEM_write_PUBKEY(fp_pub, keys->pub)) {
136 keys->msg = create_error_msg();
137 return -1;
139 strptr_t pass = { .len = 0, .ptr = "" };
140 if (passwd) {
141 pass.ptr = (char*)passwd;
142 pass.len = strlen(passwd);
144 const EVP_CIPHER *cipher = EVP_aes_256_cbc();
145 if (!PEM_write_PrivateKey(fp_priv, keys->priv, cipher, (unsigned char*)pass.ptr, (int)pass.len, NULL, NULL)) {
146 keys->msg = create_error_msg();
147 return -1;
149 return 0;
152 static str_t *create_errno_msg (const char *fname) {
153 char *errno_msg = strerror(errno);
154 str_t *msg = mkstr(errno_msg, strlen(errno_msg), 64);
155 if (fname) {
156 strnadd(&msg, CONST_STR_LEN("; \""));
157 strnadd(&msg, fname, strlen(fname));
158 strnadd(&msg, CONST_STR_LEN("\""));
160 return msg;
163 int ssl_gen_keys_fl (int nbits, const char *priv, const char *pub, const char *passwd, ssl_key_pair_t *keys) {
164 FILE *fp_priv = fopen(priv, "wt");
165 if (!fp_priv) {
166 keys->msg = create_errno_msg(priv);
167 return -1;
169 FILE *fp_pub = fopen(pub, "wt");
170 if (!fp_pub) {
171 fclose(fp_priv);
172 keys->msg = create_errno_msg(pub);
173 return -1;
175 int ret = ssl_gen_keys_fp(nbits, fp_priv, fp_pub, passwd, keys);
176 fclose(fp_pub);
177 fclose(fp_priv);
178 return ret;
181 int ssl_gen_keys_buf (int nbits, strptr_t *priv, strptr_t *pub, const char *passwd, ssl_key_pair_t *keys) {
182 priv->len = nbits;
183 priv->ptr = malloc(priv->len);
184 FILE *fp_priv = open_memstream(&priv->ptr, &priv->len);
185 if (!fp_priv) {
186 free(priv->ptr);
187 priv->ptr = NULL;
188 priv->len = 0;
189 keys->msg = create_errno_msg(NULL);
190 return -1;
192 pub->len = nbits / 2;
193 pub->ptr = malloc(pub->len);
194 FILE *fp_pub = open_memstream(&pub->ptr, &pub->len);
195 if (!fp_pub) {
196 fclose(fp_priv);
197 free(priv->ptr);
198 priv->ptr = NULL;
199 priv->len = 0;
200 free(pub->ptr);
201 pub->ptr = NULL;
202 pub->len = 0;
203 keys->msg = create_errno_msg(NULL);
204 return -1;
206 int ret = ssl_gen_keys_fp(nbits, fp_priv, fp_pub, passwd, keys);
207 if (0 == ret && (1 != fwrite("\0", 1, 1, fp_priv) || 1 != fwrite("\0", 1, 1, fp_pub))) {
208 keys->msg = create_errno_msg(NULL);
209 ret = -1;
211 fclose(fp_pub);
212 fclose(fp_priv);
213 return ret;
216 static int on_password_cb (char *buf, int size, int rwflags, void *u) {
217 size_t upass = strlen((char*)u);
218 if (upass > (size_t)size)
219 upass = (size_t)size;
220 memcpy(buf, u, upass);
221 return (int)upass;
224 int ssl_load_priv_fp (FILE *fp, const char *passwd, ssl_key_t *key) {
225 int ret = 0;
226 pem_password_cb *fn = passwd ? on_password_cb : NULL;
227 if (!PEM_read_PrivateKey(fp, &key->key, fn, (void*)passwd)) {
228 key->msg = create_error_msg();
229 ret = -1;
230 } else {
231 if (!(key->rsa = EVP_PKEY_get1_RSA(key->key))) {
232 RSA_free(key->rsa);
233 key->rsa = NULL;
234 EVP_PKEY_free(key->key);
235 key->key = NULL;
236 key->msg = create_error_msg();
237 ret = -1;
240 return ret;
243 int ssl_load_priv_fl (const char *fname, const char *passwd, ssl_key_t *key) {
244 int ret = -1;
245 FILE *fp = fopen(fname, "r");
246 if (fp) {
247 ret = ssl_load_priv_fp(fp, passwd, key);
248 fclose(fp);
249 } else
250 key->msg = create_errno_msg(fname);
251 return ret;
254 int ssl_load_priv_buf (const char *passwd, ssl_key_t *key, strptr_t *buf) {
255 int ret = -1;
256 FILE *fp = fmemopen(buf->ptr, buf->len, "r");
257 if (fp) {
258 ret = ssl_load_priv_fp(fp, passwd, key);
259 fclose(fp);
260 } else
261 key->msg = create_errno_msg(NULL);
262 return ret;
265 int ssl_load_pub_fp (FILE *fp, ssl_key_t *key) {
266 int ret = 0;
267 if (!PEM_read_PUBKEY(fp, &key->key, NULL ,NULL)) {
268 key->msg = create_error_msg();
269 ret = -1;
270 } else {
271 if (!(key->rsa = EVP_PKEY_get1_RSA(key->key))) {
272 RSA_free(key->rsa);
273 EVP_PKEY_free(key->key);
274 key->key = NULL;
275 key->msg = create_error_msg();
276 ret = -1;
279 return ret;
282 int ssl_load_pub_fl (const char *fname, ssl_key_t *key) {
283 int ret = -1;
284 FILE *fp = fopen(fname, "r");
285 if (fp) {
286 ret = ssl_load_pub_fp(fp, key);
287 fclose(fp);
288 } else
289 key->msg = create_errno_msg(fname);
290 return ret;
293 int ssl_load_pub_buf (const char *buf, size_t buf_len, ssl_key_t *key) {
294 int ret = -1;
295 FILE *fp = fmemopen((void*)buf, buf_len, "r");
296 if (fp) {
297 ret = ssl_load_pub_fp(fp, key);
298 fclose(fp);
299 } else
300 key->msg = create_errno_msg(NULL);
301 return ret;
304 int ssl_encrypt_pub (ssl_key_t *key, const char *buf, size_t buf_len, str_t **result) {
305 int encrypt_len = RSA_size(key->rsa);
306 str_t *ret = stralloc(encrypt_len, 64);
307 *result = NULL;
308 if (-1 == (encrypt_len = RSA_public_encrypt(buf_len, (unsigned char*)buf, (unsigned char*)ret->ptr, key->rsa, RSA_PKCS1_OAEP_PADDING))) {
309 key->msg = create_error_msg();
310 free(ret);
311 return -1;
313 ret->len = encrypt_len;
314 *result = ret;
315 return 0;
318 int ssl_decrypt_priv (ssl_key_t *key, const char *buf, size_t buf_len, str_t **result) {
319 int encrypt_len = RSA_size(key->rsa);
320 str_t *res = stralloc(encrypt_len, 64);
321 *result = NULL;
322 memset(res->ptr, 0, res->bufsize);
323 if (-1 == (encrypt_len = RSA_private_decrypt(buf_len, (unsigned char*)buf, (unsigned char*)res->ptr, key->rsa, RSA_PKCS1_OAEP_PADDING))) {
324 key->msg = create_error_msg();
325 free(res);
326 return -1;
328 res->len = encrypt_len;
329 *result = res;
330 return 0;
333 int ssl_sign (const unsigned char *msg, size_t mlen, unsigned char **sig, size_t *slen, int dig, ssl_key_t *pkey) {
334 int rc = -1;
335 EVP_MD_CTX *ctx;
336 const EVP_MD *md;
337 if (*sig) {
338 OPENSSL_free(*sig);
339 *sig = NULL;
341 *slen = 0;
342 if (!(ctx = EVP_MD_CTX_create()))
343 return -1;
344 if (!dig)
345 dig = NID_sha1WithRSAEncryption;
346 if (!(md = EVP_get_digestbynid(dig)) ||
347 0 == EVP_DigestInit_ex(ctx, md, NULL) ||
348 0 == EVP_DigestSignInit(ctx, NULL, md, NULL, pkey->key) ||
349 0 == EVP_DigestSignUpdate(ctx, msg, mlen) ||
350 0 == EVP_DigestSignFinal(ctx, NULL, slen) ||
351 !(*sig = OPENSSL_malloc(*slen)) ||
352 0 == EVP_DigestSignFinal(ctx, *sig, slen))
353 goto done;
354 rc = 0;
355 done:
356 if (-1 == rc) {
357 if (*sig) {
358 OPENSSL_free(*sig);
359 *sig = NULL;
361 *slen = 0;
363 EVP_MD_CTX_destroy(ctx);
364 return rc;
367 int ssl_verify (const unsigned char *msg, size_t mlen, const unsigned char *sig, size_t slen, int dig, ssl_key_t *pkey) {
368 int rc = -1;
369 EVP_MD_CTX *ctx;
370 const EVP_MD *md;
371 if (!(ctx = EVP_MD_CTX_create()))
372 return -1;
373 if (!dig)
374 dig = NID_sha1WithRSAEncryption;
375 if (!(md = EVP_get_digestbynid(dig)) ||
376 0 == EVP_DigestInit_ex(ctx, md, NULL) ||
377 0 == EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey->key) ||
378 0 == EVP_DigestVerifyUpdate(ctx, msg, mlen))
379 goto done;
380 ERR_clear_error();
381 if (0 == EVP_DigestVerifyFinal(ctx, sig, slen))
382 goto done;
383 rc = 0;
384 done:
385 EVP_MD_CTX_destroy(ctx);
386 return rc;
389 ssl_key_t *ssl_key_init () {
390 ssl_key_t *k = malloc(sizeof(ssl_key_t));
391 k->rsa = NULL;
392 k->key = NULL;
393 k->msg = NULL;
394 return k;
397 ssl_key_pair_t *ssl_key_pair_init () {
398 ssl_key_pair_t *k = malloc(sizeof(ssl_key_pair_t));
399 k->rsa = NULL;
400 k->priv = NULL;
401 k->pub = NULL;
402 k->msg = NULL;
403 return k;
406 void ssl_free_key (ssl_key_t *key) {
407 if (key->key) EVP_PKEY_free(key->key);
408 if (key->rsa) RSA_free(key->rsa);
409 free(key);
412 void ssl_free_keys (ssl_key_pair_t *keys) {
413 if (keys->rsa) RSA_free(keys->rsa);
414 if (keys->priv) EVP_PKEY_free(keys->priv);
415 if (keys->pub) EVP_PKEY_free(keys->pub);
416 if (keys->msg) free(keys->msg);
417 free(keys);