Browse code

Bring cryptoapi.c upto speed with openssl 1.1

- Replace direct access to internals of openssl structs
by corresponding methods.

v2: Remove the call to EVP_PKEY_id() as its slated for removal
from the compat layer (see also review by Stefan)

Signed-off-by: Selva Nair <selva.nair@gmail.com>
Acked-by: Steffan Karger <steffan.karger@fox-it.com>
Message-Id: <1515956662-30572-1-git-send-email-selva.nair@gmail.com>
URL: https://www.mail-archive.com/search?l=mid&q=1515956662-30572-1-git-send-email-selva.nair@gmail.com
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Selva Nair authored on 2018/01/15 04:04:22
Showing 3 changed files
... ...
@@ -944,6 +944,7 @@ if test "${with_crypto_library}" = "openssl"; then
944 944
 			RSA_meth_set_init \
945 945
 			RSA_meth_set_finish \
946 946
 			RSA_meth_set0_app_data \
947
+			RSA_meth_get0_app_data \
947 948
 			EC_GROUP_order_bits
948 949
 		]
949 950
 	)
... ...
@@ -47,6 +47,7 @@
47 47
 #include <assert.h>
48 48
 
49 49
 #include "buffer.h"
50
+#include "openssl_compat.h"
50 51
 
51 52
 /* MinGW w32api 3.17 is still incomplete when it comes to CryptoAPI while
52 53
  * MinGW32-w64 defines all macros used. This is a hack around that problem.
... ...
@@ -213,20 +214,20 @@ rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, in
213 213
 static int
214 214
 rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
215 215
 {
216
-    CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data;
216
+    CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(RSA_get_method(rsa));
217 217
     HCRYPTHASH hash;
218 218
     DWORD hash_size, len, i;
219 219
     unsigned char *buf;
220 220
 
221 221
     if (cd == NULL)
222 222
     {
223
-        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
223
+        RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
224 224
         return 0;
225 225
     }
226 226
     if (padding != RSA_PKCS1_PADDING)
227 227
     {
228 228
         /* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */
229
-        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
229
+        RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
230 230
         return 0;
231 231
     }
232 232
     /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would
... ...
@@ -236,7 +237,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i
236 236
     /* For now, we only support NID_md5_sha1 */
237 237
     if (flen != SSL_SIG_LENGTH)
238 238
     {
239
-        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
239
+        RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
240 240
         return 0;
241 241
     }
242 242
     if (!CryptCreateHash(cd->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
... ...
@@ -253,7 +254,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i
253 253
     }
254 254
     if ((int) hash_size != flen)
255 255
     {
256
-        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
256
+        RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
257 257
         CryptDestroyHash(hash);
258 258
         return 0;
259 259
     }
... ...
@@ -268,7 +269,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i
268 268
     buf = malloc(len);
269 269
     if (buf == NULL)
270 270
     {
271
-        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
271
+        RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
272 272
         CryptDestroyHash(hash);
273 273
         return 0;
274 274
     }
... ...
@@ -312,7 +313,8 @@ init(RSA *rsa)
312 312
 static int
313 313
 finish(RSA *rsa)
314 314
 {
315
-    CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data;
315
+    const RSA_METHOD *rsa_meth = RSA_get_method(rsa);
316
+    CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(rsa_meth);
316 317
 
317 318
     if (cd == NULL)
318 319
     {
... ...
@@ -326,9 +328,8 @@ finish(RSA *rsa)
326 326
     {
327 327
         CertFreeCertificateContext(cd->cert_context);
328 328
     }
329
-    free(rsa->meth->app_data);
330
-    free((char *) rsa->meth);
331
-    rsa->meth = NULL;
329
+    free(cd);
330
+    RSA_meth_free((RSA_METHOD*) rsa_meth);
332 331
     return 1;
333 332
 }
334 333
 
... ...
@@ -412,9 +413,9 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
412 412
     X509 *cert = NULL;
413 413
     RSA *rsa = NULL, *pub_rsa;
414 414
     CAPI_DATA *cd = calloc(1, sizeof(*cd));
415
-    RSA_METHOD *my_rsa_method = calloc(1, sizeof(*my_rsa_method));
415
+    RSA_METHOD *my_rsa_method = NULL;
416 416
 
417
-    if (cd == NULL || my_rsa_method == NULL)
417
+    if (cd == NULL)
418 418
     {
419 419
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
420 420
         goto err;
... ...
@@ -469,15 +470,16 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
469 469
     /* here we don't need to do CryptGetUserKey() or anything; all necessary key
470 470
      * info is in cd->cert_context, and then, in cd->crypt_prov.  */
471 471
 
472
-    my_rsa_method->name = "Microsoft CryptoAPI RSA Method";
473
-    my_rsa_method->rsa_pub_enc = rsa_pub_enc;
474
-    my_rsa_method->rsa_pub_dec = rsa_pub_dec;
475
-    my_rsa_method->rsa_priv_enc = rsa_priv_enc;
476
-    my_rsa_method->rsa_priv_dec = rsa_priv_dec;
477
-    /* my_rsa_method->init = init; */
478
-    my_rsa_method->finish = finish;
479
-    my_rsa_method->flags = RSA_METHOD_FLAG_NO_CHECK;
480
-    my_rsa_method->app_data = (char *) cd;
472
+    my_rsa_method = RSA_meth_new("Microsoft Cryptography API RSA Method",
473
+                                  RSA_METHOD_FLAG_NO_CHECK);
474
+    check_malloc_return(my_rsa_method);
475
+    RSA_meth_set_pub_enc(my_rsa_method, rsa_pub_enc);
476
+    RSA_meth_set_pub_dec(my_rsa_method, rsa_pub_dec);
477
+    RSA_meth_set_priv_enc(my_rsa_method, rsa_priv_enc);
478
+    RSA_meth_set_priv_dec(my_rsa_method, rsa_priv_dec);
479
+    RSA_meth_set_init(my_rsa_method, NULL);
480
+    RSA_meth_set_finish(my_rsa_method, finish);
481
+    RSA_meth_set0_app_data(my_rsa_method, cd);
481 482
 
482 483
     rsa = RSA_new();
483 484
     if (rsa == NULL)
... ...
@@ -486,23 +488,35 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
486 486
         goto err;
487 487
     }
488 488
 
489
-    /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(),
489
+    /* Public key in cert is NULL until we call SSL_CTX_use_certificate(),
490 490
      * so we do it here then...  */
491 491
     if (!SSL_CTX_use_certificate(ssl_ctx, cert))
492 492
     {
493 493
         goto err;
494 494
     }
495 495
     /* the public key */
496
-    pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
496
+    EVP_PKEY *pkey = X509_get0_pubkey(cert);
497
+
497 498
     /* SSL_CTX_use_certificate() increased the reference count in 'cert', so
498 499
      * we decrease it here with X509_free(), or it will never be cleaned up. */
499 500
     X509_free(cert);
500 501
     cert = NULL;
501 502
 
502
-    /* I'm not sure about what we have to fill in in the RSA, trying out stuff... */
503
-    /* rsa->n indicates the key size */
504
-    rsa->n = BN_dup(pub_rsa->n);
505
-    rsa->flags |= RSA_FLAG_EXT_PKEY;
503
+    if (!(pub_rsa = EVP_PKEY_get0_RSA(pkey)))
504
+    {
505
+        msg(M_WARN, "cryptoapicert requires an RSA certificate");
506
+        goto err;
507
+    }
508
+
509
+    /* Our private key is external, so we fill in only n and e from the public key */
510
+    const BIGNUM *n = NULL;
511
+    const BIGNUM *e = NULL;
512
+    RSA_get0_key(pub_rsa, &n, &e, NULL);
513
+    if (!RSA_set0_key(rsa, BN_dup(n), BN_dup(e), NULL))
514
+    {
515
+        goto err;
516
+    }
517
+    RSA_set_flags(rsa, RSA_flags(rsa) | RSA_FLAG_EXT_PKEY);
506 518
     if (!RSA_set_method(rsa, my_rsa_method))
507 519
     {
508 520
         goto err;
... ...
@@ -624,6 +624,20 @@ RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data)
624 624
 }
625 625
 #endif
626 626
 
627
+#if !defined(HAVE_RSA_METH_GET0_APP_DATA)
628
+/**
629
+ * Get the application data of an RSA_METHOD object
630
+ *
631
+ * @param meth               The RSA_METHOD object
632
+ * @return                   pointer to application data, may be NULL
633
+ */
634
+static inline void *
635
+RSA_meth_get0_app_data(const RSA_METHOD *meth)
636
+{
637
+    return meth ? meth->app_data : NULL;
638
+}
639
+#endif
640
+
627 641
 #if !defined(HAVE_EC_GROUP_ORDER_BITS) && !defined(OPENSSL_NO_EC)
628 642
 /**
629 643
  * Gets the number of bits of the order of an EC_GROUP