You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by mi...@apache.org on 2019/06/24 21:33:04 UTC

svn commit: r1862027 - in /apr/apr-util/branches/1.7.x: ./ crypto/ include/ include/private/ test/

Author: minfrin
Date: Mon Jun 24 21:33:04 2019
New Revision: 1862027

URL: http://svn.apache.org/viewvc?rev=1862027&view=rev
Log:
Backport 1860984:

apr_crypto_prng: Move openssl specific code into apr_crypto_openssl.

Modified:
    apr/apr-util/branches/1.7.x/   (props changed)
    apr/apr-util/branches/1.7.x/crypto/   (props changed)
    apr/apr-util/branches/1.7.x/crypto/apr_crypto.c
    apr/apr-util/branches/1.7.x/crypto/apr_crypto_commoncrypto.c
    apr/apr-util/branches/1.7.x/crypto/apr_crypto_nss.c
    apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c
    apr/apr-util/branches/1.7.x/crypto/apr_crypto_prng.c
    apr/apr-util/branches/1.7.x/include/apr_crypto.h
    apr/apr-util/branches/1.7.x/include/private/apr_crypto_internal.h
    apr/apr-util/branches/1.7.x/test/testcrypto.c

Propchange: apr/apr-util/branches/1.7.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Jun 24 21:33:04 2019
@@ -1,4 +1,4 @@
-/apr/apr/trunk:781403,781409,784519,784592,789965,794508,917837-917838,982408-982409,998533,1086937,1127053,1127648,1128838,1129433,1133587,1207704,1210524,1211987,1214516,1308087,1308131,1308318,1327636,1340286,1346865,1357761,1357772,1357780,1357966,1357968,1357979,1358295,1358480,1361811,1362241,1362248,1362252,1362255,1363076,1369681,1370626,1371811,1371817,1371919,1371923,1382174,1389154,1389169,1390461,1390477,1402870,1402897,1402903,1402907,1406088,1422413,1425356,1426442,1426448,1438960,1449308,1449314,1460185,1460243-1460244,1462219,1462224,1484271,1493715,1495887,1495889,1496407,1516261,1523479,1529554,1531009,1541054,1543399,1544846,1618843,1619438,1625247,1626561,1648830,1711657,1722547,1728958,1728963,1747941,1751567,1751806,1751898,1752008,1763665,1763667,1763669,1763672-1763673,1763842-1763843,1765378,1772414,1778153,1781391,1782042,1782045,1788335,1789947,1809394,1811470,1820080,1825311,1833359,1833366,1833382,1833421,1833425-1833426,1833440,1833449-1833451,1833456,1
 833525,1833599,1833993,1833995,1834022-1834024,1834551,1835392,1836017,1836229,1836231,1836438,1842824,1850087
+/apr/apr/trunk:781403,781409,784519,784592,789965,794508,917837-917838,982408-982409,998533,1086937,1127053,1127648,1128838,1129433,1133587,1207704,1210524,1211987,1214516,1308087,1308131,1308318,1327636,1340286,1346865,1357761,1357772,1357780,1357966,1357968,1357979,1358295,1358480,1361811,1362241,1362248,1362252,1362255,1363076,1369681,1370626,1371811,1371817,1371919,1371923,1382174,1389154,1389169,1390461,1390477,1402870,1402897,1402903,1402907,1406088,1422413,1425356,1426442,1426448,1438960,1449308,1449314,1460185,1460243-1460244,1462219,1462224,1484271,1493715,1495887,1495889,1496407,1516261,1523479,1529554,1531009,1541054,1543399,1544846,1618843,1619438,1625247,1626561,1648830,1711657,1722547,1728958,1728963,1747941,1751567,1751806,1751898,1752008,1763665,1763667,1763669,1763672-1763673,1763842-1763843,1765378,1772414,1778153,1781391,1782042,1782045,1788335,1789947,1809394,1811470,1820080,1825311,1833359,1833366,1833382,1833421,1833425-1833426,1833440,1833449-1833451,1833456,1
 833525,1833599,1833993,1833995,1834022-1834024,1834551,1835392,1836017,1836229,1836231,1836438,1842824,1850087,1860984
 /apr/apr-util/branches/1.3.x:896410,1154885
 /apr/apr-util/branches/1.4.x:1126217,1211211,1211219,1211223,1211330
 /apr/apr-util/branches/1.5.x:1757430

Propchange: apr/apr-util/branches/1.7.x/crypto/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Jun 24 21:33:04 2019
@@ -1,4 +1,4 @@
-/apr/apr/trunk/crypto:781403,781409,784519,784592,789965,794508,917837-917838,982408-982409,998533,1086937,1127053,1127648,1128838,1129433,1133587,1207704,1210524,1211987,1214516,1308087,1308131,1308318,1327636,1340286,1346865,1357761,1357772,1357780,1357966,1357968,1357979,1358295,1358480,1361811,1362241,1362248,1362252,1362255,1363076,1369681,1370626,1371811,1371817,1371919,1371923,1382174,1389154,1389169,1390461,1390477,1394552,1402870,1402897,1402903,1402907,1406088,1422413,1425356,1426442,1426448,1438960,1449308,1449314,1460185,1460243-1460244,1462219,1462224,1484271,1493715,1495887,1495889,1496407,1516261,1523479,1529554,1531009,1541054,1543399,1544846,1618843,1619438,1625247,1626561,1648830,1711657,1722547,1728958,1728963,1747941,1751806,1763665,1763667,1763669,1763672,1763842,1772414,1781391,1836438
+/apr/apr/trunk/crypto:781403,781409,784519,784592,789965,794508,917837-917838,982408-982409,998533,1086937,1127053,1127648,1128838,1129433,1133587,1207704,1210524,1211987,1214516,1308087,1308131,1308318,1327636,1340286,1346865,1357761,1357772,1357780,1357966,1357968,1357979,1358295,1358480,1361811,1362241,1362248,1362252,1362255,1363076,1369681,1370626,1371811,1371817,1371919,1371923,1382174,1389154,1389169,1390461,1390477,1394552,1402870,1402897,1402903,1402907,1406088,1422413,1425356,1426442,1426448,1438960,1449308,1449314,1460185,1460243-1460244,1462219,1462224,1484271,1493715,1495887,1495889,1496407,1516261,1523479,1529554,1531009,1541054,1543399,1544846,1618843,1619438,1625247,1626561,1648830,1711657,1722547,1728958,1728963,1747941,1751806,1763665,1763667,1763669,1763672,1763842,1772414,1781391,1836438,1860984
 /apr/apr-util/branches/1.3.x/crypto:896410,1154885
 /apr/apr-util/branches/1.4.x/crypto:1126217,1211211,1211219,1211223,1211330
 /apr/apr-util/trunk/crypto:731033-731034,731225,731236,731291,731293,731379,743986,744009,745771,747612,747623,747630,1626561

Modified: apr/apr-util/branches/1.7.x/crypto/apr_crypto.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/crypto/apr_crypto.c?rev=1862027&r1=1862026&r2=1862027&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/crypto/apr_crypto.c (original)
+++ apr/apr-util/branches/1.7.x/crypto/apr_crypto.c Mon Jun 24 21:33:04 2019
@@ -97,10 +97,6 @@ static apr_status_t apr_crypto_term(void
 APU_DECLARE(apr_status_t) apr_crypto_init(apr_pool_t *pool)
 {
     apr_pool_t *rootp;
-#if APU_HAVE_CRYPTO_PRNG
-    apr_status_t rv;
-    int flags = 0;
-#endif
 
     if (drivers != NULL) {
         return APR_SUCCESS;
@@ -123,19 +119,6 @@ APU_DECLARE(apr_status_t) apr_crypto_ini
     apr_pool_cleanup_register(rootp, NULL, apr_crypto_term,
                               apr_pool_cleanup_null);
 
-#if APU_HAVE_CRYPTO_PRNG
-    /* apr_crypto_prng_init() may already have been called with
-     * non-default parameters, so ignore APR_EREINIT.
-     */
-#if APR_HAS_THREADS
-    flags = APR_CRYPTO_PRNG_PER_THREAD;
-#endif
-    rv = apr_crypto_prng_init(pool, 0, NULL, flags);
-    if (rv != APR_SUCCESS && rv != APR_EREINIT) {
-        return rv;
-    }
-#endif
-
     return APR_SUCCESS;
 }
 

Modified: apr/apr-util/branches/1.7.x/crypto/apr_crypto_commoncrypto.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/crypto/apr_crypto_commoncrypto.c?rev=1862027&r1=1862026&r2=1862027&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/crypto/apr_crypto_commoncrypto.c (original)
+++ apr/apr-util/branches/1.7.x/crypto/apr_crypto_commoncrypto.c Mon Jun 24 21:33:04 2019
@@ -1444,20 +1444,37 @@ static apr_status_t crypto_digest(
     return status;
 }
 
+static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **psctx,
+        apr_crypto_t *f, apr_crypto_cipher_e cipher, apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
+void cprng_stream_ctx_free(cprng_stream_ctx_t *sctx)
+{
+}
+
+static apr_status_t cprng_stream_ctx_bytes(cprng_stream_ctx_t **pctx,
+        unsigned char *key, unsigned char *to, apr_size_t n, const unsigned char *z)
+{
+    return APR_ENOTIMPL;
+}
+
 /**
  * OSX Common Crypto module.
  */
 APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_commoncrypto_driver =
 {
         "commoncrypto", crypto_init, crypto_make,
-                crypto_get_block_key_digests, crypto_get_block_key_types,
-                crypto_get_block_key_modes, crypto_passphrase,
-                crypto_block_encrypt_init, crypto_block_encrypt,
-                crypto_block_encrypt_finish, crypto_block_decrypt_init,
-                crypto_block_decrypt, crypto_block_decrypt_finish,
-                crypto_digest_init, crypto_digest_update, crypto_digest_final,
-                crypto_digest, crypto_block_cleanup, crypto_digest_cleanup,
-                crypto_cleanup, crypto_shutdown, crypto_error, crypto_key
+        crypto_get_block_key_digests, crypto_get_block_key_types,
+        crypto_get_block_key_modes, crypto_passphrase,
+        crypto_block_encrypt_init, crypto_block_encrypt,
+        crypto_block_encrypt_finish, crypto_block_decrypt_init,
+        crypto_block_decrypt, crypto_block_decrypt_finish,
+        crypto_digest_init, crypto_digest_update, crypto_digest_final,
+        crypto_digest, crypto_block_cleanup, crypto_digest_cleanup,
+        crypto_cleanup, crypto_shutdown, crypto_error, crypto_key,
+        cprng_stream_ctx_make, cprng_stream_ctx_free, cprng_stream_ctx_bytes
 };
 
 #endif

Modified: apr/apr-util/branches/1.7.x/crypto/apr_crypto_nss.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/crypto/apr_crypto_nss.c?rev=1862027&r1=1862026&r2=1862027&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/crypto/apr_crypto_nss.c (original)
+++ apr/apr-util/branches/1.7.x/crypto/apr_crypto_nss.c Mon Jun 24 21:33:04 2019
@@ -1621,6 +1621,22 @@ static apr_status_t crypto_digest(
     return status;
 }
 
+static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **psctx,
+        apr_crypto_t *f, apr_crypto_cipher_e cipher, apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
+void cprng_stream_ctx_free(cprng_stream_ctx_t *sctx)
+{
+}
+
+static apr_status_t cprng_stream_ctx_bytes(cprng_stream_ctx_t **pctx,
+        unsigned char *key, unsigned char *to, apr_size_t n, const unsigned char *z)
+{
+    return APR_ENOTIMPL;
+}
+
 /**
  * NSS module.
  */
@@ -1632,7 +1648,7 @@ APU_MODULE_DECLARE_DATA const apr_crypto
     crypto_block_decrypt, crypto_block_decrypt_finish,
     crypto_digest_init, crypto_digest_update, crypto_digest_final, crypto_digest,
     crypto_block_cleanup, crypto_digest_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
-    crypto_key
+    crypto_key, cprng_stream_ctx_make, cprng_stream_ctx_free, cprng_stream_ctx_bytes
 };
 
 #endif

Modified: apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c?rev=1862027&r1=1862026&r2=1862027&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c (original)
+++ apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c Mon Jun 24 21:33:04 2019
@@ -33,6 +33,7 @@
 #include <openssl/evp.h>
 #include <openssl/rand.h>
 #include <openssl/engine.h>
+#include <openssl/obj_mac.h> /* for NID_* */
 
 #define LOG_PREFIX "apr_crypto_openssl: "
 
@@ -103,6 +104,10 @@ struct apr_crypto_digest_t {
     int digestSize;
 };
 
+struct cprng_stream_ctx_t {
+    EVP_CIPHER_CTX *ctx;
+};
+
 static struct apr_crypto_block_key_digest_t key_digests[] =
 {
 { APR_CRYPTO_DIGEST_MD5, 16, 64 },
@@ -1500,6 +1505,124 @@ static apr_status_t crypto_digest(
     return status;
 }
 
+static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **psctx,
+        apr_crypto_t *f, apr_crypto_cipher_e cipher, apr_pool_t *pool)
+{
+    cprng_stream_ctx_t *sctx;
+    EVP_CIPHER_CTX *ctx;
+    const EVP_CIPHER *ecipher;
+
+    if (pool) {
+        *psctx = sctx = apr_palloc(pool, sizeof(cprng_stream_ctx_t));
+    }
+    else {
+        *psctx = sctx = malloc(sizeof(cprng_stream_ctx_t));
+    }
+    if (!sctx) {
+        return APR_ENOMEM;
+    }
+
+    sctx->ctx = ctx = EVP_CIPHER_CTX_new();
+    if (!ctx) {
+        return APR_ENOMEM;
+    }
+
+    /* We only handle Chacha20 and AES256-CTR stream ciphers, for now.
+     * AES256-CTR should be in any openssl version of this century but is used
+     * only if Chacha20 is missing (openssl < 1.1). This is because Chacha20 is
+     * fast (enough) in software and timing attacks safe, though AES256-CTR can
+     * be faster and constant-time but only when the CPU (aesni) or some crypto
+     * hardware are in place.
+     */
+    switch (cipher) {
+    case APR_CRYPTO_CIPHER_AUTO: {
+#if defined(NID_chacha20)
+        ecipher = EVP_chacha20();
+#elif defined(NID_aes_256_ctr)
+        ecipher = EVP_aes_256_ctr();
+#else
+        return APR_ENOCIPHER;
+#endif
+    }
+    case APR_CRYPTO_CIPHER_AES_256_CTR: {
+#if defined(NID_aes_256_ctr)
+        ecipher = EVP_aes_256_ctr();
+        break;
+#else
+        return APR_ENOCIPHER;
+#endif
+    }
+    case APR_CRYPTO_CIPHER_CHACHA20_CTR: {
+#if defined(NID_chacha20)
+        ecipher = EVP_chacha20();
+        break;
+#else
+        return APR_ENOCIPHER;
+#endif
+    }
+    default: {
+        return APR_ENOCIPHER;
+    }
+    }
+
+    if (EVP_EncryptInit_ex(ctx, ecipher, f->config->engine, NULL, NULL) <= 0) {
+        EVP_CIPHER_CTX_free(ctx);
+        return APR_ENOMEM;
+    }
+
+    return APR_SUCCESS;
+}
+
+void cprng_stream_ctx_free(cprng_stream_ctx_t *sctx)
+{
+    EVP_CIPHER_CTX_free(sctx->ctx);
+}
+
+static APR_INLINE
+void cprng_stream_setkey(cprng_stream_ctx_t *sctx,
+                         const unsigned char *key,
+                         const unsigned char *iv)
+{
+#if defined(NID_chacha20)
+    /* With CHACHA20, iv=NULL is the same as zeros but it's faster
+     * to (re-)init; use that for efficiency.
+     */
+    EVP_EncryptInit_ex(sctx->ctx, NULL, NULL, key, NULL);
+#else
+    /* With AES256-CTR, iv=NULL seems to peek up and random one (for
+     * the initial CTR), while we can live with zeros (fixed CTR);
+     * efficiency still.
+     */
+    EVP_EncryptInit_ex(sctx->ctx, NULL, NULL, key, iv);
+#endif
+}
+
+static apr_status_t cprng_stream_ctx_bytes(cprng_stream_ctx_t **pctx,
+        unsigned char *key, unsigned char *to, apr_size_t n, const unsigned char *z)
+{
+    cprng_stream_ctx_t *sctx = *pctx;
+    int len;
+
+    /* We never encrypt twice with the same key, so no IV is needed (can
+     * be zeros). When EVP_EncryptInit() is called multiple times it clears
+     * its previous resources appropriately, and since we don't want the key
+     * and its keystream to reside in memory at the same time, we have to
+     * EVP_EncryptInit() twice: firstly to set the key and then finally to
+     * overwrite the key (with zeros) after the keystream is produced.
+     * As for EVP_EncryptFinish(), we don't need it either because padding
+     * is disabled (irrelevant for a stream cipher).
+     */
+    cprng_stream_setkey(sctx, key, z);
+    EVP_CIPHER_CTX_set_padding(sctx->ctx, 0);
+    EVP_EncryptUpdate(sctx->ctx, key, &len, z, CPRNG_KEY_SIZE);
+    if (n) {
+        EVP_EncryptUpdate(sctx->ctx, to, &len, z, n);
+    }
+    cprng_stream_setkey(sctx, z, z);
+
+    return APR_SUCCESS;
+}
+
 /**
  * OpenSSL module.
  */
@@ -1511,7 +1634,7 @@ APU_MODULE_DECLARE_DATA const apr_crypto
     crypto_block_decrypt, crypto_block_decrypt_finish,
     crypto_digest_init, crypto_digest_update, crypto_digest_final, crypto_digest,
     crypto_block_cleanup, crypto_digest_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
-    crypto_key
+    crypto_key, cprng_stream_ctx_make, cprng_stream_ctx_free, cprng_stream_ctx_bytes
 };
 
 #endif

Modified: apr/apr-util/branches/1.7.x/crypto/apr_crypto_prng.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/crypto/apr_crypto_prng.c?rev=1862027&r1=1862026&r2=1862027&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/crypto/apr_crypto_prng.c (original)
+++ apr/apr-util/branches/1.7.x/crypto/apr_crypto_prng.c Mon Jun 24 21:33:04 2019
@@ -41,6 +41,7 @@
 #include "apu.h"
 
 #include "apr_crypto.h"
+#include "apr_crypto_internal.h"
 
 #if APU_HAVE_CRYPTO
 #if APU_HAVE_CRYPTO_PRNG
@@ -53,8 +54,6 @@
 
 #include <stdlib.h> /* for malloc() */
 
-#define CPRNG_KEY_SIZE 32
-
 /* Be consistent with the .h (the seed is xor-ed with key on reseed). */
 #if CPRNG_KEY_SIZE != APR_CRYPTO_PRNG_SEED_SIZE
 #error apr_crypto_prng handles stream ciphers with 256bit keys only
@@ -63,113 +62,21 @@
 #define CPRNG_BUF_SIZE_MIN (CPRNG_KEY_SIZE * (8 - 1))
 #define CPRNG_BUF_SIZE_DEF (CPRNG_KEY_SIZE * (24 - 1))
 
-#if APU_HAVE_OPENSSL
-
-#include <openssl/evp.h>
-#include <openssl/sha.h>
-
-/* We only handle Chacha20 and AES256-CTR stream ciphers, for now.
- * AES256-CTR should be in any openssl version of this century but is used
- * only if Chacha20 is missing (openssl < 1.1). This is because Chacha20 is
- * fast (enough) in software and timing attacks safe, though AES256-CTR can
- * be faster and constant-time but only when the CPU (aesni) or some crypto
- * hardware are in the place.
- */
-#include <openssl/obj_mac.h> /* for NID_* */
-#if !defined(NID_chacha20) && !defined(NID_aes_256_ctr)
-/* XXX: APU_HAVE_CRYPTO_PRNG && APU_HAVE_OPENSSL shoudn't be defined! */
-#error apr_crypto_prng needs OpenSSL implementation for Chacha20 or AES256-CTR
-#endif
-
-typedef EVP_CIPHER_CTX cprng_stream_ctx_t;
-
-static apr_status_t cprng_lib_init(apr_pool_t *pool)
-{
-    return apr_crypto_lib_init("openssl", NULL, NULL, pool);
-}
-
-static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **pctx)
-{
-    EVP_CIPHER_CTX *ctx;
-    const EVP_CIPHER *cipher;
-
-    ctx = EVP_CIPHER_CTX_new();
-    if (!ctx) {
-        return APR_ENOMEM;
-    }
-
-#if defined(NID_chacha20)
-    cipher = EVP_chacha20();
-#else
-    cipher = EVP_aes_256_ctr();
-#endif
-    if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) <= 0) {
-        EVP_CIPHER_CTX_free(ctx);
-        return APR_ENOMEM;
-    }
-
-    *pctx = ctx;
-    return APR_SUCCESS;
-}
-
-static APR_INLINE
-void cprng_stream_ctx_free(cprng_stream_ctx_t *ctx)
-{
-    EVP_CIPHER_CTX_free(ctx);
-}
-
-static APR_INLINE
-apr_status_t cprng_stream_ctx_bytes(cprng_stream_ctx_t **pctx,
-                                    unsigned char *key, unsigned char *to,
-                                    apr_size_t n, const unsigned char *z)
-{
-    cprng_stream_ctx_t *ctx = *pctx;
-    int len;
-
-    /* Can be called for rekeying (key != NULL), streaming more bytes
-     * with the current key (n != 0), or both successively in a one go.
-     */
-    if (key) {
-        /* We never encrypt twice with the same key, so we can use an
-         * all zeros IV. Also EVP_EncryptInit() can be called multiple
-         * times and it will recycle its previous/replaced resources by
-         * itself, so since padding is disabled/irrelevant too we don't
-         * need EVP_EncryptFinish() after each call or before rekeying.
-         */
-#if defined(NID_chacha20)
-        /* With CHACHA20, iv=NULL is the same as zeros but it's faster
-         * to (re-)init; use that for efficiency.
-         */
-        EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);
-#else
-        /* With AES256-CTR, iv=NULL seems to peek up and random one (for
-         * the initial CTR), while we can live with zeros (fixed CTR);
-         * efficiency still.
-         */
-        EVP_EncryptInit_ex(ctx, NULL, NULL, key, z);
-#endif
-        EVP_CIPHER_CTX_set_padding(ctx, 0);
-
-        memset(key, 0, CPRNG_KEY_SIZE);
-        EVP_EncryptUpdate(ctx, key, &len, key, CPRNG_KEY_SIZE);
-    }
-    if (n) {
-        EVP_EncryptUpdate(ctx, to, &len, z, n);
-    }
-
-    return APR_SUCCESS;
-}
-
-#else /* APU_HAVE_OPENSSL */
-
-/* XXX: APU_HAVE_CRYPTO_PRNG shoudn't be defined! */
-#error apr_crypto_prng implemented with OpenSSL only for now
+#define APR_TYPEDEF_STRUCT(type, incompletion) \
+struct type { \
+   incompletion \
+   void *unk[]; \
+};
 
-#endif /* APU_HAVE_OPENSSL */
+APR_TYPEDEF_STRUCT(apr_crypto_t,
+    apr_pool_t *pool;
+    apr_crypto_driver_t *provider;
+)
 
 struct apr_crypto_prng_t {
     APR_RING_ENTRY(apr_crypto_prng_t) link;
     apr_pool_t *pool;
+    apr_crypto_t *crypto;
     cprng_stream_ctx_t *ctx;
 #if APR_HAS_THREADS
     apr_thread_mutex_t *mutex;
@@ -177,6 +84,7 @@ struct apr_crypto_prng_t {
     unsigned char *key, *buf;
     apr_size_t len, pos;
     int flags;
+    apr_crypto_cipher_e cipher;
 };
 
 static apr_crypto_prng_t *cprng_global = NULL;
@@ -219,10 +127,8 @@ static void cprng_thread_destroy(void *c
 #define cprng_ring_unlock()
 #endif /* !APR_HAS_THREADS */
 
-APU_DECLARE(apr_status_t) apr_crypto_prng_init(apr_pool_t *pool,
-                                               apr_size_t bufsize,
-                                               const unsigned char seed[],
-                                               int flags)
+APU_DECLARE(apr_status_t) apr_crypto_prng_init(apr_pool_t *pool, apr_crypto_t *crypto,
+        apr_crypto_cipher_e cipher, apr_size_t bufsize, const unsigned char seed[], int flags)
 {
     apr_status_t rv;
 
@@ -230,11 +136,6 @@ APU_DECLARE(apr_status_t) apr_crypto_prn
         return APR_EREINIT;
     }
 
-    rv = cprng_lib_init(pool);
-    if (rv != APR_SUCCESS && rv != APR_EREINIT) {
-        return rv;
-    }
-
     if (flags & APR_CRYPTO_PRNG_PER_THREAD) {
 #if !APR_HAS_THREADS
         return APR_ENOTIMPL;
@@ -266,7 +167,8 @@ APU_DECLARE(apr_status_t) apr_crypto_prn
     flags = (flags | APR_CRYPTO_PRNG_LOCKED) & ~APR_CRYPTO_PRNG_PER_THREAD;
 #endif
 
-    return apr_crypto_prng_create(&cprng_global, bufsize, flags, seed, pool);
+    return apr_crypto_prng_create(&cprng_global, crypto, cipher, bufsize, flags,
+            seed, pool);
 }
 
 APU_DECLARE(apr_status_t) apr_crypto_prng_term(void)
@@ -298,7 +200,7 @@ APU_DECLARE(apr_status_t) apr_crypto_ran
     apr_crypto_prng_t *cprng;
     void *private = NULL;
 
-    if (!cprng_thread_key) {
+    if (!cprng_thread_key || !cprng_global) {
         return APR_EINIT;
     }
 
@@ -309,8 +211,8 @@ APU_DECLARE(apr_status_t) apr_crypto_ran
 
     cprng = private;
     if (!cprng) {
-        rv = apr_crypto_prng_create(&cprng, 0, APR_CRYPTO_PRNG_PER_THREAD,
-                                    NULL, NULL);
+        rv = apr_crypto_prng_create(&cprng, cprng_global->crypto, cprng_global->cipher, 0,
+                APR_CRYPTO_PRNG_PER_THREAD, NULL, NULL);
         if (rv != APR_SUCCESS) {
             return rv;
         }
@@ -344,7 +246,7 @@ static apr_status_t cprng_cleanup(void *
     }
 
     if (cprng->ctx) {
-        cprng_stream_ctx_free(cprng->ctx);
+        cprng->crypto->provider->cprng_stream_ctx_free(cprng->ctx);
     }
 
     if (cprng->key) {
@@ -360,9 +262,8 @@ static apr_status_t cprng_cleanup(void *
 }
 
 APU_DECLARE(apr_status_t) apr_crypto_prng_create(apr_crypto_prng_t **pcprng,
-                                                 apr_size_t bufsize, int flags,
-                                                 const unsigned char seed[],
-                                                 apr_pool_t *pool)
+        apr_crypto_t *crypto, apr_crypto_cipher_e cipher, apr_size_t bufsize, int flags,
+        const unsigned char seed[], apr_pool_t *pool)
 {
     apr_status_t rv;
     apr_crypto_prng_t *cprng;
@@ -394,6 +295,7 @@ APU_DECLARE(apr_status_t) apr_crypto_prn
     if (!cprng) {
         return APR_ENOMEM;
     }
+    cprng->cipher = cipher;
     cprng->flags = flags;
     cprng->pool = pool;
 
@@ -420,7 +322,40 @@ APU_DECLARE(apr_status_t) apr_crypto_prn
     cprng->buf = cprng->key + CPRNG_KEY_SIZE;
     cprng->len = bufsize;
 
-    rv = cprng_stream_ctx_make(&cprng->ctx);
+    if (crypto) {
+        cprng->crypto = crypto;
+    }
+    else if (cprng_global && cprng_global->crypto) {
+        cprng->crypto = cprng_global->crypto;
+    }
+    else {
+        const apr_crypto_driver_t *driver = NULL;
+        if (!pool) {
+            return APR_EINVAL;
+        }
+
+        rv = apr_crypto_init(pool);
+        if (rv != APR_SUCCESS) {
+            cprng_cleanup(cprng);
+            return rv;
+        }
+
+        rv = apr_crypto_get_driver(&driver, "openssl",
+                NULL, NULL, pool);
+        if (rv != APR_SUCCESS) {
+            cprng_cleanup(cprng);
+            return rv;
+        }
+
+        rv = apr_crypto_make(&cprng->crypto, driver, NULL, pool);
+        if (rv != APR_SUCCESS) {
+            cprng_cleanup(cprng);
+            return rv;
+        }
+    }
+
+    rv = cprng->crypto->provider->cprng_stream_ctx_make(&cprng->ctx,
+            cprng->crypto, cprng->cipher, pool);
     if (rv != APR_SUCCESS) {
         cprng_cleanup(cprng);
         return rv;
@@ -479,7 +414,8 @@ static apr_status_t cprng_stream_bytes(a
 {
     apr_status_t rv;
 
-    rv = cprng_stream_ctx_bytes(&cprng->ctx, key, to, len, cprng->buf);
+    rv = cprng->crypto->provider->cprng_stream_ctx_bytes(&cprng->ctx,
+            cprng->key, to, len, cprng->buf);
     if (rv != APR_SUCCESS && len) {
         apr_crypto_memzero(to, len);
     }

Modified: apr/apr-util/branches/1.7.x/include/apr_crypto.h
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/include/apr_crypto.h?rev=1862027&r1=1862026&r2=1862027&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/include/apr_crypto.h (original)
+++ apr/apr-util/branches/1.7.x/include/apr_crypto.h Mon Jun 24 21:33:04 2019
@@ -159,6 +159,16 @@ typedef struct apr_crypto_block_key_dige
 } apr_crypto_block_key_digest_t;
 
 /**
+ * Types of ciphers supported by the apr_
+ */
+typedef enum
+{   
+    APR_CRYPTO_CIPHER_AUTO, /** Choose the recommended cipher / autodetect the cipher */
+    APR_CRYPTO_CIPHER_AES_256_CTR, /** AES 256 - CTR mode */
+    APR_CRYPTO_CIPHER_CHACHA20_CTR, /** ChaCha20 - CTR mode */
+} apr_crypto_cipher_e;
+
+/**
  * Structure representing a backend crypto driver.
  *
  * This structure is created with apr_crypto_get_driver().
@@ -1008,6 +1018,9 @@ typedef struct apr_crypto_prng_t apr_cry
  * @brief Perform global initialisation. Call once only.
  *
  * @param pool Used to allocate memory and register cleanups
+ * @param crypto The crypto context to use. If NULL, one will be created from
+ *               the recommended crypto implementation.
+ * @param cipher The cipher to use.
  * @param bufsize The size of the buffer used to cache upcoming random bytes.
  * @param seed A custom seed of \ref APR_CRYPTO_PRNG_SEED_SIZE bytes,
  *             or NULL for the seed to be gathered from system entropy.
@@ -1016,10 +1029,9 @@ typedef struct apr_crypto_prng_t apr_cry
  * @return APR_EREINIT if called more than once,
  *         any system error (APR_ENOMEM, ...).
  */
-APU_DECLARE(apr_status_t) apr_crypto_prng_init(apr_pool_t *pool,
-                                               apr_size_t bufsize,
-                                               const unsigned char seed[],
-                                               int flags);
+APU_DECLARE(apr_status_t) apr_crypto_prng_init(apr_pool_t *pool, apr_crypto_t *crypto,
+        apr_crypto_cipher_e cipher, apr_size_t bufsize, const unsigned char seed[], int flags);
+
 /**
  * @brief Terminate global initialisation if needed, before automatic cleanups.
  *
@@ -1049,13 +1061,16 @@ APU_DECLARE(apr_status_t) apr_crypto_ran
  *         any system error (APR_ENOMEM, ...).
  */
 APU_DECLARE(apr_status_t) apr_crypto_random_thread_bytes(void *buf,
-                                                         apr_size_t len);
+        apr_size_t len);
 #endif
 
 /**
  * @brief Create a standalone CPRNG.
  *
  * @param pcprng The CPRNG created.
+ * @param crypto The crypto context to use. If NULL, one will be created from
+ *               the recommended crypto implementation.
+ * @param cipher The cipher to use.
  * @param bufsize The size of the buffer used to cache upcoming random bytes.
  * @param flags \ref APR_CRYPTO_PRNG_LOCKED to control concurrent accesses,
  *              or zero.
@@ -1068,12 +1083,12 @@ APU_DECLARE(apr_status_t) apr_crypto_ran
  *             \ref apr_crypto_prng_destroy() or some memory would leak.
  * @return APR_EINVAL if \ref bufsize is too large or flags are unknown,
  *         APR_ENOTIMPL if \ref APR_CRYPTO_PRNG_LOCKED with !APR_HAS_THREADS,
+ *         APR_ENOCIPHER if neither Chacha20 nor AES-256-CTR are available,
  *         any system error (APR_ENOMEM, ...).
  */
 APU_DECLARE(apr_status_t) apr_crypto_prng_create(apr_crypto_prng_t **pcprng,
-                                                 apr_size_t bufsize, int flags,
-                                                 const unsigned char seed[],
-                                                 apr_pool_t *pool);
+        apr_crypto_t *crypto, apr_crypto_cipher_e cipher, apr_size_t bufsize,
+        int flags, const unsigned char seed[], apr_pool_t *pool);
 
 /**
  * @brief Destroy a standalone CPRNG.

Modified: apr/apr-util/branches/1.7.x/include/private/apr_crypto_internal.h
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/include/private/apr_crypto_internal.h?rev=1862027&r1=1862026&r2=1862027&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/include/private/apr_crypto_internal.h (original)
+++ apr/apr-util/branches/1.7.x/include/private/apr_crypto_internal.h Mon Jun 24 21:33:04 2019
@@ -27,6 +27,16 @@ extern "C" {
 
 #if APU_HAVE_CRYPTO
 
+/**
+ * Structure representing the streaming context for the CPRNG.
+ */
+typedef struct cprng_stream_ctx_t cprng_stream_ctx_t;
+
+/**
+ * Key size for the CPRNG.
+ */
+#define CPRNG_KEY_SIZE 32
+
 struct apr_crypto_driver_t {
 
     /** name */
@@ -363,6 +373,33 @@ struct apr_crypto_driver_t {
     apr_status_t (*key)(apr_crypto_key_t **key, const apr_crypto_key_rec_t *rec,
             const apr_crypto_t *f, apr_pool_t *p);
 
+    /**
+     * @brief Create the context for encrypting the CPRNG stream.
+     * @param pctx The pointer where the context will be returned.
+     * @param f The crypto context to use.
+     * @param cipher The cipher to use.
+     * @param pool The pool to use.
+     */
+    apr_status_t (*cprng_stream_ctx_make)(cprng_stream_ctx_t **pctx, apr_crypto_t *f,
+            apr_crypto_cipher_e cipher, apr_pool_t *pool);
+
+    /**
+     * @brief Free the context for encrypting the CPRNG stream.
+     * @param ctx The context to free.
+     */
+    void (*cprng_stream_ctx_free)(cprng_stream_ctx_t *ctx);
+
+    /**
+     * @brief Return further encrypted bytes, rekeying as necessary.
+     * @param pctx The context.
+     * @param key The key to use while rekeying.
+     * @param to Encrypted bytes are written here.
+     * @param n Length of encrypted bytes.
+     * @param z The IV to use.
+     */
+    apr_status_t (*cprng_stream_ctx_bytes)(cprng_stream_ctx_t **pctx, unsigned char *key,
+            unsigned char *to, apr_size_t n, const unsigned char *z);
+
 };
 
 #if APU_HAVE_OPENSSL

Modified: apr/apr-util/branches/1.7.x/test/testcrypto.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/test/testcrypto.c?rev=1862027&r1=1862026&r2=1862027&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/test/testcrypto.c (original)
+++ apr/apr-util/branches/1.7.x/test/testcrypto.c Mon Jun 24 21:33:04 2019
@@ -2365,10 +2365,6 @@ static void test_crypto_equals(abts_case
 }
 
 #if APU_HAVE_CRYPTO_PRNG
-#if APU_HAVE_OPENSSL
-#include <openssl/obj_mac.h> /* for NID_* */
-#endif
-#if defined(NID_chacha20)
 /*
  * KAT for CHACHA20:
  * # iv=$(printf "%.32d" 0)
@@ -2380,7 +2376,7 @@ static void test_crypto_equals(abts_case
  *               -in /dev/zero -K $key -iv $iv \
  *   | xxd -l128 -c8 -i
  */
-static const unsigned char test_PRNG_kat0[128] = {
+static const unsigned char test_PRNG_kat0_chacha20[128] = {
   0xb0, 0xfd, 0x14, 0xff, 0x96, 0xa0, 0xbd, 0xa1,
   0x54, 0xc3, 0x29, 0x08, 0x2c, 0x9c, 0x65, 0x33,
   0xbb, 0x4c, 0x94, 0x73, 0xbf, 0x5d, 0xde, 0x13,
@@ -2398,7 +2394,7 @@ static const unsigned char test_PRNG_kat
   0xb8, 0x79, 0xb5, 0x57, 0x47, 0x97, 0xa1, 0xb7,
   0x3d, 0xce, 0x7c, 0xd0, 0x9f, 0x24, 0x51, 0x01
 };
-#else
+
 /*
  * KAT for AES256-CTR:
  * # iv=$(printf "%.32d" 0)
@@ -2410,7 +2406,7 @@ static const unsigned char test_PRNG_kat
  *               -in /dev/zero -K $key -iv $iv \
  *   | xxd -l128 -c8 -i
  */
-static const unsigned char test_PRNG_kat0[128] = {
+static const unsigned char test_PRNG_kat0_aes256[128] = {
   0x79, 0x04, 0x2a, 0x33, 0xfa, 0x41, 0x1a, 0x37,
   0x97, 0x3a, 0xec, 0xa0, 0xfc, 0xde, 0x6b, 0x2b,
   0x16, 0xa4, 0x5f, 0xa1, 0x2a, 0xe3, 0xf5, 0x4c,
@@ -2428,26 +2424,49 @@ static const unsigned char test_PRNG_kat
   0xc5, 0x0c, 0xe6, 0x71, 0x42, 0xbf, 0x81, 0xb0,
   0xd1, 0x59, 0x28, 0xa1, 0x04, 0xe9, 0x8d, 0xad
 };
-#endif
 
-static void test_crypto_prng(abts_case *tc, void *data)
+static void test_crypto_prng(abts_case *tc, apr_crypto_cipher_e cipher, const unsigned char *test_PRNG_kat0)
 {
     unsigned char randbytes[128], seed[APR_CRYPTO_PRNG_SEED_SIZE];
     apr_crypto_prng_t *cprng = NULL;
     apr_pool_t *pool = NULL;
     apr_status_t rv;
     int i;
+    int flags = 0;
 
     rv = apr_pool_create(&pool, NULL);
     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
     ABTS_PTR_NOTNULL(tc, pool);
 
+#if APR_HAS_THREADS
+    flags = APR_CRYPTO_PRNG_PER_THREAD;
+#endif
+    rv = apr_crypto_prng_init(pool, NULL, cipher, 0, NULL, flags);
+
+    if (APR_ENOCIPHER == rv) {
+        apr_pool_destroy(pool);
+        return;
+    }
+
+    ABTS_ASSERT(tc, "apr_crypto_prng_init returned APR_EREINIT", rv != APR_EREINIT);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init returned APR_ENOTIMPL", rv != APR_ENOTIMPL);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init returned APR_ENOCIPHER", rv != APR_ENOCIPHER);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init failed", rv == APR_SUCCESS);
+
     for (i = 0; i < 10; ++i) {
         /* Initial seed full of zeros (deterministic) */
         memset(seed, 0, sizeof(seed));
 
-        rv = apr_crypto_prng_create(&cprng, 0, 0, seed, pool);
+        rv = apr_crypto_prng_create(&cprng, NULL, cipher, 0, 0, seed, pool);
+        ABTS_ASSERT(tc, "apr_crypto_prng_create returned APR_EINIT", rv != APR_EINIT);
+        ABTS_ASSERT(tc, "apr_crypto_prng_create returned APR_EINVAL", rv != APR_EINVAL);
+        ABTS_ASSERT(tc, "apr_crypto_prng_create returned APR_ENOTIMPL", rv != APR_ENOTIMPL);
+        ABTS_ASSERT(tc, "apr_crypto_prng_create returned APR_ENOCIPHER", rv != APR_ENOCIPHER);
+        ABTS_ASSERT(tc, "apr_crypto_prng_create returned APR_EDSOOPEN", rv != APR_EDSOOPEN);
         ABTS_ASSERT(tc, "apr_crypto_prng_create failed", rv == APR_SUCCESS);
+        if (!cprng) {
+            break;
+        }
 
         /* Second time and more, change one bit of the seed */
         if (i != 0) {
@@ -2488,6 +2507,16 @@ static void test_crypto_prng(abts_case *
     apr_pool_destroy(pool);
 }
 
+static void test_crypto_prng_aes256(abts_case *tc, void *data)
+{
+    return test_crypto_prng(tc, APR_CRYPTO_CIPHER_AES_256_CTR, test_PRNG_kat0_aes256);
+}
+
+static void test_crypto_prng_chacha20(abts_case *tc, void *data)
+{
+    return test_crypto_prng(tc, APR_CRYPTO_CIPHER_CHACHA20_CTR, test_PRNG_kat0_chacha20);
+}
+
 #if APR_HAS_FORK
 static void test_crypto_fork_random(abts_case *tc, void *data)
 {
@@ -2498,11 +2527,20 @@ static void test_crypto_fork_random(abts
     apr_size_t nbytes;
     apr_proc_t proc;
     apr_status_t rv;
+    int flags = 0;
 
     rv = apr_pool_create(&pool, NULL);
     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
     ABTS_PTR_NOTNULL(tc, pool);
 
+#if APR_HAS_THREADS
+    flags = APR_CRYPTO_PRNG_PER_THREAD;
+#endif
+    rv = apr_crypto_prng_init(pool, NULL, APR_CRYPTO_CIPHER_AUTO, 0, NULL, flags);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init returned APR_EREINIT", rv != APR_EREINIT);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init returned APR_ENOTIMPL", rv != APR_ENOTIMPL);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init failed", rv == APR_SUCCESS);
+
     rv = apr_file_pipe_create(&pread, &pwrite, p);
     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
     ABTS_PTR_NOTNULL(tc, pread);
@@ -2537,6 +2575,8 @@ static void test_crypto_fork_random(abts
 
         apr_proc_wait(&proc, &exitcode, &why, APR_WAIT);
         if (why != APR_PROC_EXIT) {
+            ABTS_ASSERT(tc, "apr_proc_wait returned APR_PROC_SIGNAL", why != APR_PROC_SIGNAL);
+            ABTS_ASSERT(tc, "apr_proc_wait returned APR_PROC_SIGNAL_CORE", why != (APR_PROC_SIGNAL | APR_PROC_SIGNAL_CORE));
             ABTS_FAIL(tc, "child terminated abnormally");
         }
         else if (exitcode != 0) {
@@ -2579,11 +2619,20 @@ static void test_crypto_thread_random(ab
     apr_pool_t *pool = NULL;
     apr_status_t rv, ret;
     int i, j;
+    int flags = 0;
 
     rv = apr_pool_create(&pool, NULL);
     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
     ABTS_PTR_NOTNULL(tc, pool);
 
+#if APR_HAS_THREADS
+    flags = APR_CRYPTO_PRNG_PER_THREAD;
+#endif
+    rv = apr_crypto_prng_init(pool, NULL, APR_CRYPTO_CIPHER_AUTO, 0, NULL, flags);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init returned APR_EREINIT", rv != APR_EREINIT);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init returned APR_ENOTIMPL", rv != APR_ENOTIMPL);
+    ABTS_ASSERT(tc, "apr_crypto_prng_init failed", rv == APR_SUCCESS);
+
     for (i = 0; i < NUM_THREADS; ++i) {
         randbytes[i] = apr_pcalloc(pool, 800);
         rv = apr_thread_create(&threads[i], NULL, thread_func,
@@ -2716,7 +2765,8 @@ abts_suite *testcrypto(abts_suite *suite
     abts_run_test(suite, test_crypto_equals, NULL);
 
 #if APU_HAVE_CRYPTO_PRNG
-    abts_run_test(suite, test_crypto_prng, NULL);
+    abts_run_test(suite, test_crypto_prng_aes256, NULL);
+    abts_run_test(suite, test_crypto_prng_chacha20, NULL);
 #if APR_HAS_FORK
     abts_run_test(suite, test_crypto_fork_random, NULL);
 #endif