parent
028c031c89
commit
0018db9e38
|
@ -1,4 +1,4 @@
|
||||||
From 4505316756e42db02b6dabe0a6b075fe52852371 Mon Sep 17 00:00:00 2001
|
From 3d11179707923b033fa413387a33296b673ff52d Mon Sep 17 00:00:00 2001
|
||||||
From: Robbie Harwood <rharwood@redhat.com>
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
Date: Thu, 14 Jan 2021 18:13:09 -0500
|
Date: Thu, 14 Jan 2021 18:13:09 -0500
|
||||||
Subject: [PATCH] Add APIs for marshalling credentials
|
Subject: [PATCH] Add APIs for marshalling credentials
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
From c76a5a01a70733c972627df0bdaa2757d323315c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
|
Date: Fri, 20 Sep 2019 16:11:29 -0400
|
||||||
|
Subject: [PATCH] Add buildsystem detection of the OpenSSL-3 KDF interface
|
||||||
|
|
||||||
|
(cherry picked from commit a3e03dfd40928c4615bd9b8546eac0c104377850)
|
||||||
|
---
|
||||||
|
src/configure.ac | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/configure.ac b/src/configure.ac
|
||||||
|
index eb6307468..9c2e816fe 100644
|
||||||
|
--- a/src/configure.ac
|
||||||
|
+++ b/src/configure.ac
|
||||||
|
@@ -282,6 +282,10 @@ AC_SUBST(CRYPTO_IMPL)
|
||||||
|
AC_SUBST(CRYPTO_IMPL_CFLAGS)
|
||||||
|
AC_SUBST(CRYPTO_IMPL_LIBS)
|
||||||
|
|
||||||
|
+if test "$CRYPTO_IMPL" = openssl; then
|
||||||
|
+ AC_CHECK_FUNCS(EVP_KDF_fetch)
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
AC_ARG_WITH([prng-alg],
|
||||||
|
AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]),
|
||||||
|
[PRNG_ALG=$withval
|
|
@ -1,4 +1,4 @@
|
||||||
From d898d94cef8e1a8772a91cd3a62255c33f109636 Mon Sep 17 00:00:00 2001
|
From c76a01279bbbbcfd296d2ead8f6e2a5bee7e8443 Mon Sep 17 00:00:00 2001
|
||||||
From: Greg Hudson <ghudson@mit.edu>
|
From: Greg Hudson <ghudson@mit.edu>
|
||||||
Date: Fri, 15 Jan 2021 14:43:34 -0500
|
Date: Fri, 15 Jan 2021 14:43:34 -0500
|
||||||
Subject: [PATCH] Add hostname canonicalization helper to k5test.py
|
Subject: [PATCH] Add hostname canonicalization helper to k5test.py
|
||||||
|
|
|
@ -0,0 +1,523 @@
|
||||||
|
From 637773266d74864118d4ae4c6ca2c7f836b400cd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
|
Date: Sat, 15 May 2021 17:35:25 -0400
|
||||||
|
Subject: [PATCH] Fix softpkcs11 build issues with openssl 3.0
|
||||||
|
|
||||||
|
EVP_PKEY_get0_RSA() has been modified to have const return type. Remove
|
||||||
|
its usages in favor of the EVP_PKEY interface. Also remove calls to
|
||||||
|
RSA_blinding_off(), which we don't need and would require a non-const
|
||||||
|
object.
|
||||||
|
|
||||||
|
Since softpkcs11 doesn't link against krb5 and can't use zap(), allocate
|
||||||
|
buffers with OPENSSL_malloc() so can use OPENSSL_clear_free().
|
||||||
|
|
||||||
|
Move several argument validation checks to the top of their functions.
|
||||||
|
|
||||||
|
Fix an incorrect log message (public vs. private key encryption).
|
||||||
|
|
||||||
|
(cherry picked from commit 8a0a2ab0296835380aede3bc190b7d10e2b162aa)
|
||||||
|
---
|
||||||
|
src/tests/softpkcs11/main.c | 306 +++++++++++++++---------------------
|
||||||
|
1 file changed, 128 insertions(+), 178 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/tests/softpkcs11/main.c b/src/tests/softpkcs11/main.c
|
||||||
|
index 1cccdfb43..500e3093d 100644
|
||||||
|
--- a/src/tests/softpkcs11/main.c
|
||||||
|
+++ b/src/tests/softpkcs11/main.c
|
||||||
|
@@ -375,10 +375,9 @@ add_st_object(void)
|
||||||
|
return NULL;
|
||||||
|
soft_token.object.objs = objs;
|
||||||
|
|
||||||
|
- o = malloc(sizeof(*o));
|
||||||
|
+ o = calloc(1, sizeof(*o));
|
||||||
|
if (o == NULL)
|
||||||
|
return NULL;
|
||||||
|
- memset(o, 0, sizeof(*o));
|
||||||
|
o->attrs = NULL;
|
||||||
|
o->num_attributes = 0;
|
||||||
|
o->object_handle = soft_token.object.num_objs;
|
||||||
|
@@ -424,7 +423,7 @@ add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
|
||||||
|
CK_ULONG modulus_bits = 0;
|
||||||
|
CK_BYTE *exponent = NULL;
|
||||||
|
size_t exponent_len = 0;
|
||||||
|
- RSA *rsa;
|
||||||
|
+ const RSA *rsa;
|
||||||
|
const BIGNUM *n, *e;
|
||||||
|
|
||||||
|
rsa = EVP_PKEY_get0_RSA(key);
|
||||||
|
@@ -445,8 +444,6 @@ add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
|
||||||
|
add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
|
||||||
|
exponent, exponent_len);
|
||||||
|
|
||||||
|
- RSA_set_method(rsa, RSA_PKCS1_OpenSSL());
|
||||||
|
-
|
||||||
|
free(modulus);
|
||||||
|
free(exponent);
|
||||||
|
}
|
||||||
|
@@ -679,10 +676,6 @@ add_certificate(char *label,
|
||||||
|
} else {
|
||||||
|
/* XXX verify keytype */
|
||||||
|
|
||||||
|
- if (key_type == CKK_RSA)
|
||||||
|
- RSA_set_method(EVP_PKEY_get0_RSA(o->u.private_key.key),
|
||||||
|
- RSA_PKCS1_OpenSSL());
|
||||||
|
-
|
||||||
|
if (X509_check_private_key(cert, o->u.private_key.key) != 1) {
|
||||||
|
EVP_PKEY_free(o->u.private_key.key);
|
||||||
|
o->u.private_key.key = NULL;
|
||||||
|
@@ -695,7 +688,7 @@ add_certificate(char *label,
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = CKR_OK;
|
||||||
|
- out:
|
||||||
|
+out:
|
||||||
|
if (ret != CKR_OK) {
|
||||||
|
st_logf("something went wrong when adding cert!\n");
|
||||||
|
|
||||||
|
@@ -1224,8 +1217,6 @@ C_Login(CK_SESSION_HANDLE hSession,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX check keytype */
|
||||||
|
- RSA_set_method(EVP_PKEY_get0_RSA(o->u.private_key.key),
|
||||||
|
- RSA_PKCS1_OpenSSL());
|
||||||
|
|
||||||
|
if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) {
|
||||||
|
EVP_PKEY_free(o->u.private_key.key);
|
||||||
|
@@ -1495,8 +1486,9 @@ C_Encrypt(CK_SESSION_HANDLE hSession,
|
||||||
|
struct st_object *o;
|
||||||
|
void *buffer = NULL;
|
||||||
|
CK_RV ret;
|
||||||
|
- RSA *rsa;
|
||||||
|
- int padding, len, buffer_len, padding_len;
|
||||||
|
+ size_t buffer_len;
|
||||||
|
+ int padding, padding_len;
|
||||||
|
+ EVP_PKEY_CTX *ctx = NULL;
|
||||||
|
|
||||||
|
st_logf("Encrypt\n");
|
||||||
|
|
||||||
|
@@ -1512,22 +1504,18 @@ C_Encrypt(CK_SESSION_HANDLE hSession,
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
- rsa = EVP_PKEY_get0_RSA(o->u.public_key);
|
||||||
|
-
|
||||||
|
- if (rsa == NULL)
|
||||||
|
- return CKR_ARGUMENTS_BAD;
|
||||||
|
-
|
||||||
|
- RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
|
||||||
|
-
|
||||||
|
- buffer_len = RSA_size(rsa);
|
||||||
|
-
|
||||||
|
- buffer = malloc(buffer_len);
|
||||||
|
- if (buffer == NULL) {
|
||||||
|
- ret = CKR_DEVICE_MEMORY;
|
||||||
|
+ if (pulEncryptedDataLen == NULL) {
|
||||||
|
+ st_logf("pulEncryptedDataLen NULL\n");
|
||||||
|
+ ret = CKR_ARGUMENTS_BAD;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (pData == NULL) {
|
||||||
|
+ st_logf("data NULL\n");
|
||||||
|
+ ret = CKR_ARGUMENTS_BAD;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = CKR_OK;
|
||||||
|
switch(state->encrypt_mechanism->mechanism) {
|
||||||
|
case CKM_RSA_PKCS:
|
||||||
|
padding = RSA_PKCS1_PADDING;
|
||||||
|
@@ -1542,40 +1530,41 @@ C_Encrypt(CK_SESSION_HANDLE hSession,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ctx = EVP_PKEY_CTX_new(o->u.public_key, NULL);
|
||||||
|
+ if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0 ||
|
||||||
|
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
|
||||||
|
+ EVP_PKEY_encrypt(ctx, NULL, &buffer_len, pData, ulDataLen) <= 0) {
|
||||||
|
+ ret = CKR_DEVICE_ERROR;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if ((CK_ULONG)buffer_len + padding_len < ulDataLen) {
|
||||||
|
ret = CKR_ARGUMENTS_BAD;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pulEncryptedDataLen == NULL) {
|
||||||
|
- st_logf("pulEncryptedDataLen NULL\n");
|
||||||
|
- ret = CKR_ARGUMENTS_BAD;
|
||||||
|
+ buffer = OPENSSL_malloc(buffer_len);
|
||||||
|
+ if (buffer == NULL) {
|
||||||
|
+ ret = CKR_DEVICE_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pData == NULL_PTR) {
|
||||||
|
- st_logf("data NULL\n");
|
||||||
|
- ret = CKR_ARGUMENTS_BAD;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- len = RSA_public_encrypt(ulDataLen, pData, buffer, rsa, padding);
|
||||||
|
- if (len <= 0) {
|
||||||
|
+ if (EVP_PKEY_encrypt(ctx, buffer, &buffer_len, pData, ulDataLen) <= 0) {
|
||||||
|
ret = CKR_DEVICE_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- if (len > buffer_len)
|
||||||
|
- abort();
|
||||||
|
+ st_logf("Encrypt done\n");
|
||||||
|
|
||||||
|
- if (pEncryptedData != NULL_PTR)
|
||||||
|
- memcpy(pEncryptedData, buffer, len);
|
||||||
|
- *pulEncryptedDataLen = len;
|
||||||
|
+ if (pEncryptedData != NULL)
|
||||||
|
+ memcpy(pEncryptedData, buffer, buffer_len);
|
||||||
|
+ *pulEncryptedDataLen = buffer_len;
|
||||||
|
|
||||||
|
- out:
|
||||||
|
- if (buffer) {
|
||||||
|
- memset(buffer, 0, buffer_len);
|
||||||
|
- free(buffer);
|
||||||
|
- }
|
||||||
|
+ ret = CKR_OK;
|
||||||
|
+out:
|
||||||
|
+ if (buffer != NULL)
|
||||||
|
+ OPENSSL_clear_free(buffer, buffer_len);
|
||||||
|
+ if (ctx != NULL)
|
||||||
|
+ EVP_PKEY_CTX_free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1646,8 +1635,9 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
|
||||||
|
struct st_object *o;
|
||||||
|
void *buffer = NULL;
|
||||||
|
CK_RV ret;
|
||||||
|
- RSA *rsa;
|
||||||
|
- int padding, len, buffer_len, padding_len;
|
||||||
|
+ size_t buffer_len;
|
||||||
|
+ int padding, padding_len;
|
||||||
|
+ EVP_PKEY_CTX *ctx = NULL;
|
||||||
|
|
||||||
|
st_logf("Decrypt\n");
|
||||||
|
|
||||||
|
@@ -1663,22 +1653,18 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
- rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);
|
||||||
|
-
|
||||||
|
- if (rsa == NULL)
|
||||||
|
- return CKR_ARGUMENTS_BAD;
|
||||||
|
-
|
||||||
|
- RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
|
||||||
|
-
|
||||||
|
- buffer_len = RSA_size(rsa);
|
||||||
|
-
|
||||||
|
- buffer = malloc(buffer_len);
|
||||||
|
- if (buffer == NULL) {
|
||||||
|
- ret = CKR_DEVICE_MEMORY;
|
||||||
|
+ if (pulDataLen == NULL) {
|
||||||
|
+ st_logf("pulDataLen NULL\n");
|
||||||
|
+ ret = CKR_ARGUMENTS_BAD;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (pEncryptedData == NULL_PTR) {
|
||||||
|
+ st_logf("data NULL\n");
|
||||||
|
+ ret = CKR_ARGUMENTS_BAD;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = CKR_OK;
|
||||||
|
switch(state->decrypt_mechanism->mechanism) {
|
||||||
|
case CKM_RSA_PKCS:
|
||||||
|
padding = RSA_PKCS1_PADDING;
|
||||||
|
@@ -1693,41 +1679,43 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ctx = EVP_PKEY_CTX_new(o->u.private_key.key, NULL);
|
||||||
|
+ if (ctx == NULL || EVP_PKEY_decrypt_init(ctx) <= 0 ||
|
||||||
|
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
|
||||||
|
+ EVP_PKEY_decrypt(ctx, NULL, &buffer_len, pEncryptedData,
|
||||||
|
+ ulEncryptedDataLen) <= 0) {
|
||||||
|
+ ret = CKR_DEVICE_ERROR;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if ((CK_ULONG)buffer_len + padding_len < ulEncryptedDataLen) {
|
||||||
|
ret = CKR_ARGUMENTS_BAD;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pulDataLen == NULL) {
|
||||||
|
- st_logf("pulDataLen NULL\n");
|
||||||
|
- ret = CKR_ARGUMENTS_BAD;
|
||||||
|
+ buffer = OPENSSL_malloc(buffer_len);
|
||||||
|
+ if (buffer == NULL) {
|
||||||
|
+ ret = CKR_DEVICE_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pEncryptedData == NULL_PTR) {
|
||||||
|
- st_logf("data NULL\n");
|
||||||
|
- ret = CKR_ARGUMENTS_BAD;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- len = RSA_private_decrypt(ulEncryptedDataLen, pEncryptedData, buffer,
|
||||||
|
- rsa, padding);
|
||||||
|
- if (len <= 0) {
|
||||||
|
+ if (EVP_PKEY_decrypt(ctx, buffer, &buffer_len, pEncryptedData,
|
||||||
|
+ ulEncryptedDataLen) <= 0) {
|
||||||
|
ret = CKR_DEVICE_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- if (len > buffer_len)
|
||||||
|
- abort();
|
||||||
|
+ st_logf("Decrypt done\n");
|
||||||
|
|
||||||
|
if (pData != NULL_PTR)
|
||||||
|
- memcpy(pData, buffer, len);
|
||||||
|
- *pulDataLen = len;
|
||||||
|
+ memcpy(pData, buffer, buffer_len);
|
||||||
|
+ *pulDataLen = buffer_len;
|
||||||
|
|
||||||
|
- out:
|
||||||
|
- if (buffer) {
|
||||||
|
- memset(buffer, 0, buffer_len);
|
||||||
|
- free(buffer);
|
||||||
|
- }
|
||||||
|
+ ret = CKR_OK;
|
||||||
|
+out:
|
||||||
|
+ if (buffer != NULL)
|
||||||
|
+ OPENSSL_clear_free(buffer, buffer_len);
|
||||||
|
+ if (ctx != NULL)
|
||||||
|
+ EVP_PKEY_CTX_free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1806,8 +1794,9 @@ C_Sign(CK_SESSION_HANDLE hSession,
|
||||||
|
struct st_object *o;
|
||||||
|
void *buffer = NULL;
|
||||||
|
CK_RV ret;
|
||||||
|
- RSA *rsa;
|
||||||
|
- int padding, len, buffer_len, padding_len;
|
||||||
|
+ int padding, padding_len;
|
||||||
|
+ size_t buffer_len;
|
||||||
|
+ EVP_PKEY_CTX *ctx = NULL;
|
||||||
|
|
||||||
|
st_logf("Sign\n");
|
||||||
|
VERIFY_SESSION_HANDLE(hSession, &state);
|
||||||
|
@@ -1822,18 +1811,15 @@ C_Sign(CK_SESSION_HANDLE hSession,
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
- rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);
|
||||||
|
+ if (pulSignatureLen == NULL) {
|
||||||
|
+ st_logf("signature len NULL\n");
|
||||||
|
+ ret = CKR_ARGUMENTS_BAD;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (rsa == NULL)
|
||||||
|
- return CKR_ARGUMENTS_BAD;
|
||||||
|
-
|
||||||
|
- RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
|
||||||
|
-
|
||||||
|
- buffer_len = RSA_size(rsa);
|
||||||
|
-
|
||||||
|
- buffer = malloc(buffer_len);
|
||||||
|
- if (buffer == NULL) {
|
||||||
|
- ret = CKR_DEVICE_MEMORY;
|
||||||
|
+ if (pData == NULL_PTR) {
|
||||||
|
+ st_logf("data NULL\n");
|
||||||
|
+ ret = CKR_ARGUMENTS_BAD;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1851,43 +1837,41 @@ C_Sign(CK_SESSION_HANDLE hSession,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ctx = EVP_PKEY_CTX_new(o->u.private_key.key, NULL);
|
||||||
|
+ if (ctx == NULL || EVP_PKEY_sign_init(ctx) <= 0 ||
|
||||||
|
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
|
||||||
|
+ EVP_PKEY_sign(ctx, NULL, &buffer_len, pData, ulDataLen) <= 0) {
|
||||||
|
+ ret = CKR_DEVICE_ERROR;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if ((CK_ULONG)buffer_len < ulDataLen + padding_len) {
|
||||||
|
ret = CKR_ARGUMENTS_BAD;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pulSignatureLen == NULL) {
|
||||||
|
- st_logf("signature len NULL\n");
|
||||||
|
- ret = CKR_ARGUMENTS_BAD;
|
||||||
|
+ buffer = OPENSSL_malloc(buffer_len);
|
||||||
|
+ if (buffer == NULL) {
|
||||||
|
+ ret = CKR_DEVICE_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pData == NULL_PTR) {
|
||||||
|
- st_logf("data NULL\n");
|
||||||
|
- ret = CKR_ARGUMENTS_BAD;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- len = RSA_private_encrypt(ulDataLen, pData, buffer, rsa, padding);
|
||||||
|
- st_logf("private encrypt done\n");
|
||||||
|
- if (len <= 0) {
|
||||||
|
+ if (EVP_PKEY_sign(ctx, buffer, &buffer_len, pData, ulDataLen) <= 0) {
|
||||||
|
ret = CKR_DEVICE_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- if (len > buffer_len)
|
||||||
|
- abort();
|
||||||
|
+ st_logf("Sign done\n");
|
||||||
|
|
||||||
|
- if (pSignature != NULL_PTR)
|
||||||
|
- memcpy(pSignature, buffer, len);
|
||||||
|
- *pulSignatureLen = len;
|
||||||
|
+ if (pSignature != NULL)
|
||||||
|
+ memcpy(pSignature, buffer, buffer_len);
|
||||||
|
+ *pulSignatureLen = buffer_len;
|
||||||
|
|
||||||
|
ret = CKR_OK;
|
||||||
|
-
|
||||||
|
- out:
|
||||||
|
- if (buffer) {
|
||||||
|
- memset(buffer, 0, buffer_len);
|
||||||
|
- free(buffer);
|
||||||
|
- }
|
||||||
|
+out:
|
||||||
|
+ if (buffer != NULL)
|
||||||
|
+ OPENSSL_clear_free(buffer, buffer_len);
|
||||||
|
+ if (ctx != NULL)
|
||||||
|
+ EVP_PKEY_CTX_free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1951,10 +1935,9 @@ C_Verify(CK_SESSION_HANDLE hSession,
|
||||||
|
{
|
||||||
|
struct session_state *state;
|
||||||
|
struct st_object *o;
|
||||||
|
- void *buffer = NULL;
|
||||||
|
CK_RV ret;
|
||||||
|
- RSA *rsa;
|
||||||
|
- int padding, len, buffer_len;
|
||||||
|
+ int padding;
|
||||||
|
+ EVP_PKEY_CTX *ctx = NULL;
|
||||||
|
|
||||||
|
st_logf("Verify\n");
|
||||||
|
VERIFY_SESSION_HANDLE(hSession, &state);
|
||||||
|
@@ -1969,39 +1952,6 @@ C_Verify(CK_SESSION_HANDLE hSession,
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
- rsa = EVP_PKEY_get0_RSA(o->u.public_key);
|
||||||
|
-
|
||||||
|
- if (rsa == NULL)
|
||||||
|
- return CKR_ARGUMENTS_BAD;
|
||||||
|
-
|
||||||
|
- RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
|
||||||
|
-
|
||||||
|
- buffer_len = RSA_size(rsa);
|
||||||
|
-
|
||||||
|
- buffer = malloc(buffer_len);
|
||||||
|
- if (buffer == NULL) {
|
||||||
|
- ret = CKR_DEVICE_MEMORY;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ret = CKR_OK;
|
||||||
|
- switch(state->verify_mechanism->mechanism) {
|
||||||
|
- case CKM_RSA_PKCS:
|
||||||
|
- padding = RSA_PKCS1_PADDING;
|
||||||
|
- break;
|
||||||
|
- case CKM_RSA_X_509:
|
||||||
|
- padding = RSA_NO_PADDING;
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- ret = CKR_FUNCTION_NOT_SUPPORTED;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if ((CK_ULONG)buffer_len < ulDataLen) {
|
||||||
|
- ret = CKR_ARGUMENTS_BAD;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (pSignature == NULL) {
|
||||||
|
st_logf("signature NULL\n");
|
||||||
|
ret = CKR_ARGUMENTS_BAD;
|
||||||
|
@@ -2014,34 +1964,35 @@ C_Verify(CK_SESSION_HANDLE hSession,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- len = RSA_public_decrypt(ulDataLen, pData, buffer, rsa, padding);
|
||||||
|
- st_logf("private encrypt done\n");
|
||||||
|
- if (len <= 0) {
|
||||||
|
+ switch(state->verify_mechanism->mechanism) {
|
||||||
|
+ case CKM_RSA_PKCS:
|
||||||
|
+ padding = RSA_PKCS1_PADDING;
|
||||||
|
+ break;
|
||||||
|
+ case CKM_RSA_X_509:
|
||||||
|
+ padding = RSA_NO_PADDING;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ ret = CKR_FUNCTION_NOT_SUPPORTED;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ctx = EVP_PKEY_CTX_new(o->u.public_key, NULL);
|
||||||
|
+ if (ctx == NULL || EVP_PKEY_verify_init(ctx) <= 0 ||
|
||||||
|
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
|
||||||
|
+ EVP_PKEY_verify(ctx, pSignature, ulSignatureLen, pData,
|
||||||
|
+ ulDataLen) <= 0) {
|
||||||
|
ret = CKR_DEVICE_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- if (len > buffer_len)
|
||||||
|
- abort();
|
||||||
|
+ st_logf("Verify done\n");
|
||||||
|
|
||||||
|
- if ((CK_ULONG)len != ulSignatureLen) {
|
||||||
|
- ret = CKR_GENERAL_ERROR;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (memcmp(pSignature, buffer, len) != 0) {
|
||||||
|
- ret = CKR_GENERAL_ERROR;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- out:
|
||||||
|
- if (buffer) {
|
||||||
|
- memset(buffer, 0, buffer_len);
|
||||||
|
- free(buffer);
|
||||||
|
- }
|
||||||
|
+ ret = CKR_OK;
|
||||||
|
+out:
|
||||||
|
+ if (ctx != NULL)
|
||||||
|
+ EVP_PKEY_CTX_free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
CK_RV
|
||||||
|
C_VerifyUpdate(CK_SESSION_HANDLE hSession,
|
||||||
|
CK_BYTE_PTR pPart,
|
||||||
|
@@ -2072,7 +2023,6 @@ C_GenerateRandom(CK_SESSION_HANDLE hSession,
|
||||||
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
CK_FUNCTION_LIST funcs = {
|
||||||
|
{ 2, 11 },
|
||||||
|
C_Initialize,
|
|
@ -0,0 +1,268 @@
|
||||||
|
From 64a276e3485b7066a3c630d018ca44dabeb7b6c7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
|
Date: Sat, 15 May 2021 21:18:06 -0400
|
||||||
|
Subject: [PATCH] Handle OpenSSL 3's providers
|
||||||
|
|
||||||
|
OpenSSL 3 compartmentalizes what algorithms it uses, which for us means
|
||||||
|
another hoop to jump through to use dubious cryptography. Right now, we
|
||||||
|
need to load "legacy" in order to access MD4 and RC4.
|
||||||
|
|
||||||
|
(cherry picked from commit faac961a0d02c7818aad87c765eb344b87e668fa)
|
||||||
|
[rharwood@redhat.com: des3 removal, rc4 FIPSification]
|
||||||
|
---
|
||||||
|
src/configure.ac | 1 +
|
||||||
|
src/lib/crypto/openssl/enc_provider/aes.c | 16 +++++++
|
||||||
|
.../crypto/openssl/enc_provider/camellia.c | 16 +++++++
|
||||||
|
src/lib/crypto/openssl/enc_provider/rc4.c | 4 ++
|
||||||
|
.../crypto/openssl/hash_provider/hash_evp.c | 5 ++
|
||||||
|
src/lib/crypto/openssl/init.c | 47 +++++++++++++++++++
|
||||||
|
.../preauth/pkinit/pkinit_crypto_openssl.c | 25 ++++++++--
|
||||||
|
7 files changed, 111 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/configure.ac b/src/configure.ac
|
||||||
|
index 9c2e816fe..20066918b 100644
|
||||||
|
--- a/src/configure.ac
|
||||||
|
+++ b/src/configure.ac
|
||||||
|
@@ -284,6 +284,7 @@ AC_SUBST(CRYPTO_IMPL_LIBS)
|
||||||
|
|
||||||
|
if test "$CRYPTO_IMPL" = openssl; then
|
||||||
|
AC_CHECK_FUNCS(EVP_KDF_fetch)
|
||||||
|
+ AC_CHECK_FUNCS(OSSL_PROVIDER_load)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_WITH([prng-alg],
|
||||||
|
diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c
|
||||||
|
index 6b4622fe9..31c90a69d 100644
|
||||||
|
--- a/src/lib/crypto/openssl/enc_provider/aes.c
|
||||||
|
+++ b/src/lib/crypto/openssl/enc_provider/aes.c
|
||||||
|
@@ -68,6 +68,10 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
||||||
|
EVP_CIPHER_CTX *ctx;
|
||||||
|
struct iov_cursor cursor;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
ctx = EVP_CIPHER_CTX_new();
|
||||||
|
if (ctx == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
@@ -102,6 +106,10 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
||||||
|
EVP_CIPHER_CTX *ctx;
|
||||||
|
struct iov_cursor cursor;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
ctx = EVP_CIPHER_CTX_new();
|
||||||
|
if (ctx == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
@@ -137,6 +145,10 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
||||||
|
struct iov_cursor cursor;
|
||||||
|
AES_KEY enck;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
memset(iv_cts,0,sizeof(iv_cts));
|
||||||
|
if (ivec && ivec->data){
|
||||||
|
if (ivec->length != sizeof(iv_cts))
|
||||||
|
@@ -190,6 +202,10 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
||||||
|
struct iov_cursor cursor;
|
||||||
|
AES_KEY deck;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
memset(iv_cts,0,sizeof(iv_cts));
|
||||||
|
if (ivec && ivec->data){
|
||||||
|
if (ivec->length != sizeof(iv_cts))
|
||||||
|
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
|
||||||
|
index f79679a0b..7cc7fc6fb 100644
|
||||||
|
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
|
||||||
|
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
|
||||||
|
@@ -92,6 +92,10 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
||||||
|
EVP_CIPHER_CTX *ctx;
|
||||||
|
struct iov_cursor cursor;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
ctx = EVP_CIPHER_CTX_new();
|
||||||
|
if (ctx == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
@@ -126,6 +130,10 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
||||||
|
EVP_CIPHER_CTX *ctx;
|
||||||
|
struct iov_cursor cursor;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
ctx = EVP_CIPHER_CTX_new();
|
||||||
|
if (ctx == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
@@ -161,6 +169,10 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
||||||
|
struct iov_cursor cursor;
|
||||||
|
CAMELLIA_KEY enck;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
memset(iv_cts,0,sizeof(iv_cts));
|
||||||
|
if (ivec && ivec->data){
|
||||||
|
if (ivec->length != sizeof(iv_cts))
|
||||||
|
@@ -214,6 +226,10 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
||||||
|
struct iov_cursor cursor;
|
||||||
|
CAMELLIA_KEY deck;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
memset(iv_cts,0,sizeof(iv_cts));
|
||||||
|
if (ivec && ivec->data){
|
||||||
|
if (ivec->length != sizeof(iv_cts))
|
||||||
|
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
|
||||||
|
index 9bf407899..4e7af3555 100644
|
||||||
|
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
|
||||||
|
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
|
||||||
|
@@ -69,6 +69,10 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
|
||||||
|
if (FIPS_mode())
|
||||||
|
return KRB5_CRYPTO_INTERNAL;
|
||||||
|
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
arcstate = (state != NULL) ? (void *)state->data : NULL;
|
||||||
|
if (arcstate != NULL) {
|
||||||
|
ctx = arcstate->ctx;
|
||||||
|
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||||
|
index 2eb5139c0..09d7b3896 100644
|
||||||
|
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||||
|
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||||
|
@@ -41,6 +41,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
|
||||||
|
const krb5_data *d;
|
||||||
|
size_t i;
|
||||||
|
int ok;
|
||||||
|
+ krb5_error_code ret;
|
||||||
|
+
|
||||||
|
+ ret = krb5int_crypto_init();
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
|
||||||
|
if (output->length != (unsigned int)EVP_MD_size(type))
|
||||||
|
return KRB5_CRYPTO_INTERNAL;
|
||||||
|
diff --git a/src/lib/crypto/openssl/init.c b/src/lib/crypto/openssl/init.c
|
||||||
|
index 1139bce53..8342dece1 100644
|
||||||
|
--- a/src/lib/crypto/openssl/init.c
|
||||||
|
+++ b/src/lib/crypto/openssl/init.c
|
||||||
|
@@ -26,6 +26,51 @@
|
||||||
|
|
||||||
|
#include "crypto_int.h"
|
||||||
|
|
||||||
|
+#ifdef HAVE_OSSL_PROVIDER_LOAD
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Starting in OpenSSL 3, algorithms are grouped into containers called
|
||||||
|
+ * "providers", not all of which are loaded by default. At time of writing,
|
||||||
|
+ * we need MD4 and RC4 from the legacy provider. Oddly, 3DES is not in
|
||||||
|
+ * legacy.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <openssl/provider.h>
|
||||||
|
+
|
||||||
|
+OSSL_PROVIDER *legacy_provider = NULL;
|
||||||
|
+OSSL_PROVIDER *default_provider = NULL;
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+krb5int_crypto_impl_init(void)
|
||||||
|
+{
|
||||||
|
+ legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
|
||||||
|
+ default_provider = OSSL_PROVIDER_load(NULL, "default");
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Someone might build openssl without the legacy provider. They will
|
||||||
|
+ * have a bad time, but some things will still work. I don't know think
|
||||||
|
+ * this configuration is worth supporting.
|
||||||
|
+ */
|
||||||
|
+ if (legacy_provider == NULL || default_provider == NULL)
|
||||||
|
+ abort();
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+krb5int_crypto_impl_cleanup(void)
|
||||||
|
+{
|
||||||
|
+ if (legacy_provider != NULL)
|
||||||
|
+ OSSL_PROVIDER_unload(legacy_provider);
|
||||||
|
+ if (default_provider != NULL)
|
||||||
|
+ OSSL_PROVIDER_unload(default_provider);
|
||||||
|
+
|
||||||
|
+ legacy_provider = NULL;
|
||||||
|
+ default_provider = NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#else /* !HAVE_OSSL_PROVIDER_LOAD */
|
||||||
|
+
|
||||||
|
int
|
||||||
|
krb5int_crypto_impl_init(void)
|
||||||
|
{
|
||||||
|
@@ -36,3 +81,5 @@ void
|
||||||
|
krb5int_crypto_impl_cleanup(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
index 350c2118a..284702432 100644
|
||||||
|
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
@@ -44,6 +44,14 @@
|
||||||
|
#include <openssl/params.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifdef HAVE_OSSL_PROVIDER_LOAD
|
||||||
|
+#include <openssl/provider.h>
|
||||||
|
+
|
||||||
|
+/* TODO these leak - where to release them? */
|
||||||
|
+OSSL_PROVIDER *legacy_provider = NULL;
|
||||||
|
+OSSL_PROVIDER *default_provider = NULL;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
|
||||||
|
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
|
||||||
|
|
||||||
|
@@ -2937,12 +2945,23 @@ cleanup:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Initialize OpenSSL. */
|
||||||
|
int
|
||||||
|
pkinit_openssl_init()
|
||||||
|
{
|
||||||
|
- /* Initialize OpenSSL. */
|
||||||
|
- ERR_load_crypto_strings();
|
||||||
|
- OpenSSL_add_all_algorithms();
|
||||||
|
+#ifdef HAVE_OSSL_PROVIDER_LOAD
|
||||||
|
+ legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
|
||||||
|
+ default_provider = OSSL_PROVIDER_load(NULL, "default");
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Someone might build openssl without the legacy provider. They will
|
||||||
|
+ * have a bad time, but some things will still work. I don't know think
|
||||||
|
+ * this configuration is worth supporting.
|
||||||
|
+ */
|
||||||
|
+ if (legacy_provider == NULL || default_provider == NULL)
|
||||||
|
+ abort();
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
From f135f51b0ec59d320f79cd961411231084364489 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
|
Date: Wed, 19 May 2021 19:33:34 -0400
|
||||||
|
Subject: [PATCH] Handle SSL_read changed behavior on server hangup
|
||||||
|
|
||||||
|
(cherry picked from commit 948e3c5b89fcfdb64ea5af177c7e30a6ce8a477b)
|
||||||
|
---
|
||||||
|
src/include/k5-trace.h | 2 --
|
||||||
|
src/lib/krb5/os/sendto_kdc.c | 5 +++--
|
||||||
|
2 files changed, 3 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
|
||||||
|
index 79b5a7a85..7bd385d68 100644
|
||||||
|
--- a/src/include/k5-trace.h
|
||||||
|
+++ b/src/include/k5-trace.h
|
||||||
|
@@ -395,8 +395,6 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
|
||||||
|
TRACE(c, "Received answer ({int} bytes) from {raddr}", len, raddr)
|
||||||
|
#define TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(c, raddr) \
|
||||||
|
TRACE(c, "HTTPS error connecting to {raddr}", raddr)
|
||||||
|
-#define TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(c, raddr) \
|
||||||
|
- TRACE(c, "HTTPS error receiving from {raddr}", raddr)
|
||||||
|
#define TRACE_SENDTO_KDC_HTTPS_ERROR_SEND(c, raddr) \
|
||||||
|
TRACE(c, "HTTPS error sending to {raddr}", raddr)
|
||||||
|
#define TRACE_SENDTO_KDC_HTTPS_SEND(c, raddr) \
|
||||||
|
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
index 0eedec175..e874130d9 100644
|
||||||
|
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
@@ -1320,8 +1320,9 @@ https_read_bytes(krb5_context context, struct conn_state *conn,
|
||||||
|
} else if (st == WANT_WRITE) {
|
||||||
|
cm_write(selstate, conn->fd);
|
||||||
|
} else if (st == ERROR_TLS) {
|
||||||
|
- TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(context, &conn->addr);
|
||||||
|
- kill_conn(context, conn, selstate);
|
||||||
|
+ /* In OpenSSL 3, a server hangup is a TLS error. Rely on our decoder
|
||||||
|
+ * to handle this instead. */
|
||||||
|
+ return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
From 8c57937f3ca793fe3f8fdd636be0bc11c24069bc Mon Sep 17 00:00:00 2001
|
From e33835c4b6c6ce71757e9f659db03afa4bfd9a9a Mon Sep 17 00:00:00 2001
|
||||||
From: Greg Hudson <ghudson@mit.edu>
|
From: Greg Hudson <ghudson@mit.edu>
|
||||||
Date: Fri, 15 Jan 2021 13:51:34 -0500
|
Date: Fri, 15 Jan 2021 13:51:34 -0500
|
||||||
Subject: [PATCH] Support host-based GSS initiator names
|
Subject: [PATCH] Support host-based GSS initiator names
|
||||||
|
|
|
@ -0,0 +1,483 @@
|
||||||
|
From 454a1a84ad161bd892c5b388edac09322c08cd06 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
|
Date: Fri, 4 Oct 2019 14:49:29 -0400
|
||||||
|
Subject: [PATCH] Use OpenSSL's KBKDF and KRB5KDF for deriving long-term keys
|
||||||
|
|
||||||
|
If supported, use OpenSSL-provided KBKDF (aes-sha2 and camellia) and
|
||||||
|
KRB5KDF (3des and aes-sha1). We already use OpenSSL's PBKDF2 where
|
||||||
|
appropriate. OpenSSL added support for these KDFs in 3.0.
|
||||||
|
|
||||||
|
(cherry picked from commit ef8d11f6fb1232201c9efd2ae2ed567023fb85d2)
|
||||||
|
---
|
||||||
|
src/lib/crypto/krb/derive.c | 411 ++++++++++++++++++++++++++++--------
|
||||||
|
1 file changed, 326 insertions(+), 85 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
|
||||||
|
index 6707a7308..1f07464e0 100644
|
||||||
|
--- a/src/lib/crypto/krb/derive.c
|
||||||
|
+++ b/src/lib/crypto/krb/derive.c
|
||||||
|
@@ -27,6 +27,12 @@
|
||||||
|
|
||||||
|
#include "crypto_int.h"
|
||||||
|
|
||||||
|
+#ifdef HAVE_EVP_KDF_FETCH
|
||||||
|
+#include <openssl/core_names.h>
|
||||||
|
+#include <openssl/evp.h>
|
||||||
|
+#include <openssl/kdf.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static krb5_key
|
||||||
|
find_cached_dkey(struct derived_key *list, const krb5_data *constant)
|
||||||
|
{
|
||||||
|
@@ -77,55 +83,253 @@ cleanup:
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef HAVE_EVP_KDF_FETCH
|
||||||
|
static krb5_error_code
|
||||||
|
-derive_random_rfc3961(const struct krb5_enc_provider *enc,
|
||||||
|
- krb5_key inkey, krb5_data *outrnd,
|
||||||
|
- const krb5_data *in_constant)
|
||||||
|
+openssl_kbdkf_counter_hmac(const struct krb5_hash_provider *hash,
|
||||||
|
+ krb5_key inkey, krb5_data *outrnd,
|
||||||
|
+ const krb5_data *label, const krb5_data *context)
|
||||||
|
{
|
||||||
|
- size_t blocksize, keybytes, n;
|
||||||
|
krb5_error_code ret;
|
||||||
|
- krb5_data block = empty_data();
|
||||||
|
+ EVP_KDF *kdf = NULL;
|
||||||
|
+ EVP_KDF_CTX *kctx = NULL;
|
||||||
|
+ OSSL_PARAM params[6];
|
||||||
|
+ size_t i = 0;
|
||||||
|
+ char *digest;
|
||||||
|
|
||||||
|
- blocksize = enc->block_size;
|
||||||
|
- keybytes = enc->keybytes;
|
||||||
|
+ /* On NULL hash, preserve default behavior for pbkdf2_string_to_key(). */
|
||||||
|
+ if (hash == NULL || !strcmp(hash->hash_name, "SHA1")) {
|
||||||
|
+ digest = "SHA1";
|
||||||
|
+ } else if (!strcmp(hash->hash_name, "SHA-256")) {
|
||||||
|
+ digest = "SHA256";
|
||||||
|
+ } else if (!strcmp(hash->hash_name, "SHA-384")) {
|
||||||
|
+ digest = "SHA384";
|
||||||
|
+ } else {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (blocksize == 1)
|
||||||
|
- return KRB5_BAD_ENCTYPE;
|
||||||
|
- if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
|
||||||
|
+ kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
|
||||||
|
+ if (!kdf) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kctx = EVP_KDF_CTX_new(kdf);
|
||||||
|
+ if (!kctx) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
|
||||||
|
+ digest, 0);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
|
||||||
|
+ "HMAC", 0);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
|
||||||
|
+ inkey->keyblock.contents,
|
||||||
|
+ inkey->keyblock.length);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
|
||||||
|
+ context->data,
|
||||||
|
+ context->length);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
|
||||||
|
+ label->data,
|
||||||
|
+ label->length);
|
||||||
|
+ params[i] = OSSL_PARAM_construct_end();
|
||||||
|
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
|
||||||
|
+ params) <= 0) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = 0;
|
||||||
|
+done:
|
||||||
|
+ if (ret)
|
||||||
|
+ zap(outrnd->data, outrnd->length);
|
||||||
|
+ EVP_KDF_free(kdf);
|
||||||
|
+ EVP_KDF_CTX_free(kctx);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static krb5_error_code
|
||||||
|
+openssl_kbkdf_feedback_cmac(const struct krb5_enc_provider *enc,
|
||||||
|
+ krb5_key inkey, krb5_data *outrnd,
|
||||||
|
+ const krb5_data *in_constant)
|
||||||
|
+{
|
||||||
|
+ krb5_error_code ret;
|
||||||
|
+ EVP_KDF *kdf = NULL;
|
||||||
|
+ EVP_KDF_CTX *kctx = NULL;
|
||||||
|
+ OSSL_PARAM params[7];
|
||||||
|
+ size_t i = 0;
|
||||||
|
+ char *cipher;
|
||||||
|
+ static unsigned char zeroes[16];
|
||||||
|
+
|
||||||
|
+ memset(zeroes, 0, sizeof(zeroes));
|
||||||
|
+
|
||||||
|
+ if (!memcmp(enc, &krb5int_enc_camellia128, sizeof(*enc))) {
|
||||||
|
+ cipher = "CAMELLIA-128-CBC";
|
||||||
|
+ } else if (!memcmp(enc, &krb5int_enc_camellia256, sizeof(*enc))) {
|
||||||
|
+ cipher = "CAMELLIA-256-CBC";
|
||||||
|
+ } else {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
|
||||||
|
+ if (!kdf) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kctx = EVP_KDF_CTX_new(kdf);
|
||||||
|
+ if (!kctx) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE,
|
||||||
|
+ "FEEDBACK", 0);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
|
||||||
|
+ "CMAC", 0);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
|
||||||
|
+ cipher, 0);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
|
||||||
|
+ inkey->keyblock.contents,
|
||||||
|
+ inkey->keyblock.length);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
|
||||||
|
+ in_constant->data,
|
||||||
|
+ in_constant->length);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
|
||||||
|
+ zeroes, sizeof(zeroes));
|
||||||
|
+ params[i] = OSSL_PARAM_construct_end();
|
||||||
|
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
|
||||||
|
+ params) <= 0) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = 0;
|
||||||
|
+done:
|
||||||
|
+ if (ret)
|
||||||
|
+ zap(outrnd->data, outrnd->length);
|
||||||
|
+ EVP_KDF_free(kdf);
|
||||||
|
+ EVP_KDF_CTX_free(kctx);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static krb5_error_code
|
||||||
|
+openssl_krb5kdf(const struct krb5_enc_provider *enc, krb5_key inkey,
|
||||||
|
+ krb5_data *outrnd, const krb5_data *in_constant)
|
||||||
|
+{
|
||||||
|
+ krb5_error_code ret;
|
||||||
|
+ EVP_KDF *kdf = NULL;
|
||||||
|
+ EVP_KDF_CTX *kctx = NULL;
|
||||||
|
+ OSSL_PARAM params[4];
|
||||||
|
+ size_t i = 0;
|
||||||
|
+ char *cipher;
|
||||||
|
+
|
||||||
|
+ if (inkey->keyblock.length != enc->keylength ||
|
||||||
|
+ outrnd->length != enc->keybytes) {
|
||||||
|
+ return KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!memcmp(enc, &krb5int_enc_aes128, sizeof(*enc))) {
|
||||||
|
+ cipher = "AES-128-CBC";
|
||||||
|
+ } else if (!memcmp(enc, &krb5int_enc_aes256, sizeof(*enc))) {
|
||||||
|
+ cipher = "AES-256-CBC";
|
||||||
|
+ } else if (!memcmp(enc, &krb5int_enc_des3, sizeof(*enc))) {
|
||||||
|
+ cipher = "DES-EDE3-CBC";
|
||||||
|
+ } else {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kdf = EVP_KDF_fetch(NULL, "KRB5KDF", NULL);
|
||||||
|
+ if (kdf == NULL) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kctx = EVP_KDF_CTX_new(kdf);
|
||||||
|
+ if (kctx == NULL) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
|
||||||
|
+ cipher, 0);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
|
||||||
|
+ inkey->keyblock.contents,
|
||||||
|
+ inkey->keyblock.length);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_CONSTANT,
|
||||||
|
+ in_constant->data,
|
||||||
|
+ in_constant->length);
|
||||||
|
+ params[i] = OSSL_PARAM_construct_end();
|
||||||
|
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
|
||||||
|
+ params) <= 0) {
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = 0;
|
||||||
|
+done:
|
||||||
|
+ if (ret)
|
||||||
|
+ zap(outrnd->data, outrnd->length);
|
||||||
|
+ EVP_KDF_free(kdf);
|
||||||
|
+ EVP_KDF_CTX_free(kctx);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#else /* HAVE_EVP_KDF_FETCH */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * NIST SP800-108 KDF in counter mode (section 5.1).
|
||||||
|
+ * Parameters:
|
||||||
|
+ * - HMAC (with hash as the hash provider) is the PRF.
|
||||||
|
+ * - A block counter of four bytes is used.
|
||||||
|
+ * - Four bytes are used to encode the output length in the PRF input.
|
||||||
|
+ *
|
||||||
|
+ * There are no uses requiring more than a single PRF invocation.
|
||||||
|
+ */
|
||||||
|
+static krb5_error_code
|
||||||
|
+builtin_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
|
||||||
|
+ krb5_key inkey, krb5_data *outrnd,
|
||||||
|
+ const krb5_data *label,
|
||||||
|
+ const krb5_data *context)
|
||||||
|
+{
|
||||||
|
+ krb5_crypto_iov iov[5];
|
||||||
|
+ krb5_error_code ret;
|
||||||
|
+ krb5_data prf;
|
||||||
|
+ unsigned char ibuf[4], lbuf[4];
|
||||||
|
+
|
||||||
|
+ if (hash == NULL || outrnd->length > hash->hashsize)
|
||||||
|
return KRB5_CRYPTO_INTERNAL;
|
||||||
|
|
||||||
|
/* Allocate encryption data buffer. */
|
||||||
|
- ret = alloc_data(&block, blocksize);
|
||||||
|
+ ret = alloc_data(&prf, hash->hashsize);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
- /* Initialize the input block. */
|
||||||
|
- if (in_constant->length == blocksize) {
|
||||||
|
- memcpy(block.data, in_constant->data, blocksize);
|
||||||
|
- } else {
|
||||||
|
- krb5int_nfold(in_constant->length * 8,
|
||||||
|
- (unsigned char *) in_constant->data,
|
||||||
|
- blocksize * 8, (unsigned char *) block.data);
|
||||||
|
- }
|
||||||
|
+ /* [i]2: four-byte big-endian binary string giving the block counter (1) */
|
||||||
|
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
+ iov[0].data = make_data(ibuf, sizeof(ibuf));
|
||||||
|
+ store_32_be(1, ibuf);
|
||||||
|
+ /* Label */
|
||||||
|
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
+ iov[1].data = *label;
|
||||||
|
+ /* 0x00: separator byte */
|
||||||
|
+ iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
+ iov[2].data = make_data("", 1);
|
||||||
|
+ /* Context */
|
||||||
|
+ iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
+ iov[3].data = *context;
|
||||||
|
+ /* [L]2: four-byte big-endian binary string giving the output length */
|
||||||
|
+ iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
+ iov[4].data = make_data(lbuf, sizeof(lbuf));
|
||||||
|
+ store_32_be(outrnd->length * 8, lbuf);
|
||||||
|
|
||||||
|
- /* Loop encrypting the blocks until enough key bytes are generated. */
|
||||||
|
- n = 0;
|
||||||
|
- while (n < keybytes) {
|
||||||
|
- ret = encrypt_block(enc, inkey, &block);
|
||||||
|
- if (ret)
|
||||||
|
- goto cleanup;
|
||||||
|
-
|
||||||
|
- if ((keybytes - n) <= blocksize) {
|
||||||
|
- memcpy(outrnd->data + n, block.data, (keybytes - n));
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- memcpy(outrnd->data + n, block.data, blocksize);
|
||||||
|
- n += blocksize;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-cleanup:
|
||||||
|
- zapfree(block.data, blocksize);
|
||||||
|
+ ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
|
||||||
|
+ if (!ret)
|
||||||
|
+ memcpy(outrnd->data, prf.data, outrnd->length);
|
||||||
|
+ zapfree(prf.data, prf.length);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -139,9 +343,9 @@ cleanup:
|
||||||
|
* - Four bytes are used to encode the output length in the PRF input.
|
||||||
|
*/
|
||||||
|
static krb5_error_code
|
||||||
|
-derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
|
||||||
|
- krb5_key inkey, krb5_data *outrnd,
|
||||||
|
- const krb5_data *in_constant)
|
||||||
|
+builtin_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
|
||||||
|
+ krb5_key inkey, krb5_data *outrnd,
|
||||||
|
+ const krb5_data *in_constant)
|
||||||
|
{
|
||||||
|
size_t blocksize, keybytes, n;
|
||||||
|
krb5_crypto_iov iov[6];
|
||||||
|
@@ -204,56 +408,94 @@ cleanup:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * NIST SP800-108 KDF in counter mode (section 5.1).
|
||||||
|
- * Parameters:
|
||||||
|
- * - HMAC (with hash as the hash provider) is the PRF.
|
||||||
|
- * - A block counter of four bytes is used.
|
||||||
|
- * - Four bytes are used to encode the output length in the PRF input.
|
||||||
|
- *
|
||||||
|
- * There are no uses requiring more than a single PRF invocation.
|
||||||
|
- */
|
||||||
|
+static krb5_error_code
|
||||||
|
+builtin_derive_random_rfc3961(const struct krb5_enc_provider *enc,
|
||||||
|
+ krb5_key inkey, krb5_data *outrnd,
|
||||||
|
+ const krb5_data *in_constant)
|
||||||
|
+{
|
||||||
|
+ size_t blocksize, keybytes, n;
|
||||||
|
+ krb5_error_code ret;
|
||||||
|
+ krb5_data block = empty_data();
|
||||||
|
+
|
||||||
|
+ blocksize = enc->block_size;
|
||||||
|
+ keybytes = enc->keybytes;
|
||||||
|
+
|
||||||
|
+ if (blocksize == 1)
|
||||||
|
+ return KRB5_BAD_ENCTYPE;
|
||||||
|
+ if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
|
||||||
|
+ return KRB5_CRYPTO_INTERNAL;
|
||||||
|
+
|
||||||
|
+ /* Allocate encryption data buffer. */
|
||||||
|
+ ret = alloc_data(&block, blocksize);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Initialize the input block. */
|
||||||
|
+ if (in_constant->length == blocksize) {
|
||||||
|
+ memcpy(block.data, in_constant->data, blocksize);
|
||||||
|
+ } else {
|
||||||
|
+ krb5int_nfold(in_constant->length * 8,
|
||||||
|
+ (unsigned char *) in_constant->data,
|
||||||
|
+ blocksize * 8, (unsigned char *) block.data);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Loop encrypting the blocks until enough key bytes are generated. */
|
||||||
|
+ n = 0;
|
||||||
|
+ while (n < keybytes) {
|
||||||
|
+ ret = encrypt_block(enc, inkey, &block);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ if ((keybytes - n) <= blocksize) {
|
||||||
|
+ memcpy(outrnd->data + n, block.data, (keybytes - n));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(outrnd->data + n, block.data, blocksize);
|
||||||
|
+ n += blocksize;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+cleanup:
|
||||||
|
+ zapfree(block.data, blocksize);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+#endif /* HAVE_EVP_KDF_FETCH */
|
||||||
|
+
|
||||||
|
krb5_error_code
|
||||||
|
k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
|
||||||
|
krb5_key inkey, krb5_data *outrnd,
|
||||||
|
const krb5_data *label, const krb5_data *context)
|
||||||
|
{
|
||||||
|
- krb5_crypto_iov iov[5];
|
||||||
|
- krb5_error_code ret;
|
||||||
|
- krb5_data prf;
|
||||||
|
- unsigned char ibuf[4], lbuf[4];
|
||||||
|
+#ifdef HAVE_EVP_KDF_FETCH
|
||||||
|
+ return openssl_kbdkf_counter_hmac(hash, inkey, outrnd, label, context);
|
||||||
|
+#else
|
||||||
|
+ return builtin_sp800_108_counter_hmac(hash, inkey, outrnd, label,
|
||||||
|
+ context);
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
|
||||||
|
- if (hash == NULL || outrnd->length > hash->hashsize)
|
||||||
|
- return KRB5_CRYPTO_INTERNAL;
|
||||||
|
+static krb5_error_code
|
||||||
|
+sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
|
||||||
|
+ krb5_key inkey, krb5_data *outrnd,
|
||||||
|
+ const krb5_data *in_constant)
|
||||||
|
+{
|
||||||
|
+#ifdef HAVE_EVP_KDF_FETCH
|
||||||
|
+ return openssl_kbkdf_feedback_cmac(enc, inkey, outrnd, in_constant);
|
||||||
|
+#else
|
||||||
|
+ return builtin_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
|
||||||
|
- /* Allocate encryption data buffer. */
|
||||||
|
- ret = alloc_data(&prf, hash->hashsize);
|
||||||
|
- if (ret)
|
||||||
|
- return ret;
|
||||||
|
-
|
||||||
|
- /* [i]2: four-byte big-endian binary string giving the block counter (1) */
|
||||||
|
- iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
- iov[0].data = make_data(ibuf, sizeof(ibuf));
|
||||||
|
- store_32_be(1, ibuf);
|
||||||
|
- /* Label */
|
||||||
|
- iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
- iov[1].data = *label;
|
||||||
|
- /* 0x00: separator byte */
|
||||||
|
- iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
- iov[2].data = make_data("", 1);
|
||||||
|
- /* Context */
|
||||||
|
- iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
- iov[3].data = *context;
|
||||||
|
- /* [L]2: four-byte big-endian binary string giving the output length */
|
||||||
|
- iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
|
||||||
|
- iov[4].data = make_data(lbuf, sizeof(lbuf));
|
||||||
|
- store_32_be(outrnd->length * 8, lbuf);
|
||||||
|
-
|
||||||
|
- ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
|
||||||
|
- if (!ret)
|
||||||
|
- memcpy(outrnd->data, prf.data, outrnd->length);
|
||||||
|
- zapfree(prf.data, prf.length);
|
||||||
|
- return ret;
|
||||||
|
+static krb5_error_code
|
||||||
|
+derive_random_rfc3961(const struct krb5_enc_provider *enc,
|
||||||
|
+ krb5_key inkey, krb5_data *outrnd,
|
||||||
|
+ const krb5_data *in_constant)
|
||||||
|
+{
|
||||||
|
+#ifdef HAVE_EVP_KDF_FETCH
|
||||||
|
+ return openssl_krb5kdf(enc, inkey, outrnd, in_constant);
|
||||||
|
+#else
|
||||||
|
+ return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5_error_code
|
||||||
|
@@ -268,8 +510,7 @@ krb5int_derive_random(const struct krb5_enc_provider *enc,
|
||||||
|
case DERIVE_RFC3961:
|
||||||
|
return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
|
||||||
|
case DERIVE_SP800_108_CMAC:
|
||||||
|
- return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd,
|
||||||
|
- in_constant);
|
||||||
|
+ return sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
|
||||||
|
case DERIVE_SP800_108_HMAC:
|
||||||
|
return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant,
|
||||||
|
&empty);
|
|
@ -0,0 +1,408 @@
|
||||||
|
From cfdd0501ffea9cbe9343d1ff1e597df1689b547b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
|
Date: Fri, 20 Sep 2019 17:20:59 -0400
|
||||||
|
Subject: [PATCH] Use OpenSSL's SSKDF in PKINIT when available
|
||||||
|
|
||||||
|
Starting in 3.0, OpenSSL implements SSKDF, which is the basis of our
|
||||||
|
id-pkinit-kdf (RFC 8636). Factor out common setup code around
|
||||||
|
other_info. Adjust code to comply to existing style.
|
||||||
|
|
||||||
|
(cherry picked from commit 4376a22e41fb639be31daf81275a332d3f930996)
|
||||||
|
---
|
||||||
|
.../preauth/pkinit/pkinit_crypto_openssl.c | 294 +++++++++++-------
|
||||||
|
1 file changed, 181 insertions(+), 113 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
index e1153344e..350c2118a 100644
|
||||||
|
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
@@ -38,6 +38,12 @@
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
+#ifdef HAVE_EVP_KDF_FETCH
|
||||||
|
+#include <openssl/core_names.h>
|
||||||
|
+#include <openssl/kdf.h>
|
||||||
|
+#include <openssl/params.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
|
||||||
|
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
|
||||||
|
|
||||||
|
@@ -2294,15 +2300,16 @@ cleanup:
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-/**
|
||||||
|
+/*
|
||||||
|
* Given an algorithm_identifier, this function returns the hash length
|
||||||
|
* and EVP function associated with that algorithm.
|
||||||
|
+ *
|
||||||
|
+ * RFC 8636 defines a SHA384 variant, but we don't use it.
|
||||||
|
*/
|
||||||
|
static krb5_error_code
|
||||||
|
-pkinit_alg_values(krb5_context context,
|
||||||
|
- const krb5_data *alg_id,
|
||||||
|
- size_t *hash_bytes,
|
||||||
|
- const EVP_MD *(**func)(void))
|
||||||
|
+pkinit_alg_values(krb5_context context, const krb5_data *alg_id,
|
||||||
|
+ size_t *hash_bytes, const EVP_MD *(**func)(void),
|
||||||
|
+ char **hash_name)
|
||||||
|
{
|
||||||
|
*hash_bytes = 0;
|
||||||
|
*func = NULL;
|
||||||
|
@@ -2311,18 +2318,21 @@ pkinit_alg_values(krb5_context context,
|
||||||
|
krb5_pkinit_sha1_oid_len))) {
|
||||||
|
*hash_bytes = 20;
|
||||||
|
*func = &EVP_sha1;
|
||||||
|
+ *hash_name = strdup("SHA1");
|
||||||
|
return 0;
|
||||||
|
} else if ((alg_id->length == krb5_pkinit_sha256_oid_len) &&
|
||||||
|
(0 == memcmp(alg_id->data, krb5_pkinit_sha256_oid,
|
||||||
|
krb5_pkinit_sha256_oid_len))) {
|
||||||
|
*hash_bytes = 32;
|
||||||
|
*func = &EVP_sha256;
|
||||||
|
+ *hash_name = strdup("SHA256");
|
||||||
|
return 0;
|
||||||
|
} else if ((alg_id->length == krb5_pkinit_sha512_oid_len) &&
|
||||||
|
(0 == memcmp(alg_id->data, krb5_pkinit_sha512_oid,
|
||||||
|
krb5_pkinit_sha512_oid_len))) {
|
||||||
|
*hash_bytes = 64;
|
||||||
|
*func = &EVP_sha512;
|
||||||
|
+ *hash_name = strdup("SHA512");
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
krb5_set_error_message(context, KRB5_ERR_BAD_S2K_PARAMS,
|
||||||
|
@@ -2331,11 +2341,60 @@ pkinit_alg_values(krb5_context context,
|
||||||
|
}
|
||||||
|
} /* pkinit_alg_values() */
|
||||||
|
|
||||||
|
+#ifdef HAVE_EVP_KDF_FETCH
|
||||||
|
+static krb5_error_code
|
||||||
|
+openssl_sskdf(krb5_context context, size_t hash_bytes, krb5_data *key,
|
||||||
|
+ krb5_data *info, char *out, size_t out_len, char *digest)
|
||||||
|
+{
|
||||||
|
+ krb5_error_code ret;
|
||||||
|
+ EVP_KDF *kdf = NULL;
|
||||||
|
+ EVP_KDF_CTX *kctx = NULL;
|
||||||
|
+ OSSL_PARAM params[4];
|
||||||
|
+ size_t i = 0;
|
||||||
|
|
||||||
|
-/* pkinit_alg_agility_kdf() --
|
||||||
|
- * This function generates a key using the KDF described in
|
||||||
|
- * draft_ietf_krb_wg_pkinit_alg_agility-04.txt. The algorithm is
|
||||||
|
- * described as follows:
|
||||||
|
+ if (digest == NULL) {
|
||||||
|
+ ret = oerr(context, ENOMEM,
|
||||||
|
+ _("Failed to allocate space for digest algorithm name"));
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
|
||||||
|
+ if (kdf == NULL) {
|
||||||
|
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL, _("Failed to fetch SSKDF"));
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kctx = EVP_KDF_CTX_new(kdf);
|
||||||
|
+ if (!kctx) {
|
||||||
|
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL,
|
||||||
|
+ _("Failed to instantiate SSKDF"));
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
|
||||||
|
+ digest, 0);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
|
||||||
|
+ key->data, key->length);
|
||||||
|
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
|
||||||
|
+ info->data, info->length);
|
||||||
|
+ params[i] = OSSL_PARAM_construct_end();
|
||||||
|
+ if (EVP_KDF_derive(kctx, (unsigned char *)out, out_len, params) <= 0) {
|
||||||
|
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL,
|
||||||
|
+ _("Failed to derive key using SSKDF"));
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = 0;
|
||||||
|
+done:
|
||||||
|
+ EVP_KDF_free(kdf);
|
||||||
|
+ EVP_KDF_CTX_free(kctx);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+#else
|
||||||
|
+/*
|
||||||
|
+ * Generate a key using the KDF described in RFC 8636, also known as SSKDF
|
||||||
|
+ * (single-step kdf). Our caller precomputes `reps`, but otherwise the
|
||||||
|
+ * algorithm is as follows:
|
||||||
|
*
|
||||||
|
* 1. reps = keydatalen (K) / hash length (H)
|
||||||
|
*
|
||||||
|
@@ -2349,95 +2408,16 @@ pkinit_alg_values(krb5_context context,
|
||||||
|
*
|
||||||
|
* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes.
|
||||||
|
*/
|
||||||
|
-krb5_error_code
|
||||||
|
-pkinit_alg_agility_kdf(krb5_context context,
|
||||||
|
- krb5_data *secret,
|
||||||
|
- krb5_data *alg_oid,
|
||||||
|
- krb5_const_principal party_u_info,
|
||||||
|
- krb5_const_principal party_v_info,
|
||||||
|
- krb5_enctype enctype,
|
||||||
|
- krb5_data *as_req,
|
||||||
|
- krb5_data *pk_as_rep,
|
||||||
|
- krb5_keyblock *key_block)
|
||||||
|
+static krb5_error_code
|
||||||
|
+builtin_sskdf(krb5_context context, unsigned int reps, size_t hash_len,
|
||||||
|
+ const EVP_MD *(*EVP_func)(void), krb5_data *secret,
|
||||||
|
+ krb5_data *other_info, char *out, size_t out_len)
|
||||||
|
{
|
||||||
|
- krb5_error_code retval = 0;
|
||||||
|
+ krb5_error_code ret = 0;
|
||||||
|
|
||||||
|
- unsigned int reps = 0;
|
||||||
|
- uint32_t counter = 1; /* Does this type work on Windows? */
|
||||||
|
+ uint32_t counter = 1;
|
||||||
|
size_t offset = 0;
|
||||||
|
- size_t hash_len = 0;
|
||||||
|
- size_t rand_len = 0;
|
||||||
|
- size_t key_len = 0;
|
||||||
|
- krb5_data random_data;
|
||||||
|
- krb5_sp80056a_other_info other_info_fields;
|
||||||
|
- krb5_pkinit_supp_pub_info supp_pub_info_fields;
|
||||||
|
- krb5_data *other_info = NULL;
|
||||||
|
- krb5_data *supp_pub_info = NULL;
|
||||||
|
- krb5_algorithm_identifier alg_id;
|
||||||
|
EVP_MD_CTX *ctx = NULL;
|
||||||
|
- const EVP_MD *(*EVP_func)(void);
|
||||||
|
-
|
||||||
|
- /* initialize random_data here to make clean-up safe */
|
||||||
|
- random_data.length = 0;
|
||||||
|
- random_data.data = NULL;
|
||||||
|
-
|
||||||
|
- /* allocate and initialize the key block */
|
||||||
|
- key_block->magic = 0;
|
||||||
|
- key_block->enctype = enctype;
|
||||||
|
- if (0 != (retval = krb5_c_keylengths(context, enctype, &rand_len,
|
||||||
|
- &key_len)))
|
||||||
|
- goto cleanup;
|
||||||
|
-
|
||||||
|
- random_data.length = rand_len;
|
||||||
|
- key_block->length = key_len;
|
||||||
|
-
|
||||||
|
- if (NULL == (key_block->contents = malloc(key_block->length))) {
|
||||||
|
- retval = ENOMEM;
|
||||||
|
- goto cleanup;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- memset (key_block->contents, 0, key_block->length);
|
||||||
|
-
|
||||||
|
- /* If this is anonymous pkinit, use the anonymous principle for party_u_info */
|
||||||
|
- if (party_u_info && krb5_principal_compare_any_realm(context, party_u_info,
|
||||||
|
- krb5_anonymous_principal()))
|
||||||
|
- party_u_info = (krb5_principal)krb5_anonymous_principal();
|
||||||
|
-
|
||||||
|
- if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func)))
|
||||||
|
- goto cleanup;
|
||||||
|
-
|
||||||
|
- /* 1. reps = keydatalen (K) / hash length (H) */
|
||||||
|
- reps = key_block->length/hash_len;
|
||||||
|
-
|
||||||
|
- /* ... and round up, if necessary */
|
||||||
|
- if (key_block->length > (reps * hash_len))
|
||||||
|
- reps++;
|
||||||
|
-
|
||||||
|
- /* Allocate enough space in the random data buffer to hash directly into
|
||||||
|
- * it, even if the last hash will make it bigger than the key length. */
|
||||||
|
- if (NULL == (random_data.data = malloc(reps * hash_len))) {
|
||||||
|
- retval = ENOMEM;
|
||||||
|
- goto cleanup;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* Encode the ASN.1 octet string for "SuppPubInfo" */
|
||||||
|
- supp_pub_info_fields.enctype = enctype;
|
||||||
|
- supp_pub_info_fields.as_req = *as_req;
|
||||||
|
- supp_pub_info_fields.pk_as_rep = *pk_as_rep;
|
||||||
|
- if (0 != ((retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
|
||||||
|
- &supp_pub_info))))
|
||||||
|
- goto cleanup;
|
||||||
|
-
|
||||||
|
- /* Now encode the ASN.1 octet string for "OtherInfo" */
|
||||||
|
- memset(&alg_id, 0, sizeof alg_id);
|
||||||
|
- alg_id.algorithm = *alg_oid; /*alias*/
|
||||||
|
-
|
||||||
|
- other_info_fields.algorithm_identifier = alg_id;
|
||||||
|
- other_info_fields.party_u_info = (krb5_principal) party_u_info;
|
||||||
|
- other_info_fields.party_v_info = (krb5_principal) party_v_info;
|
||||||
|
- other_info_fields.supp_pub_info = *supp_pub_info;
|
||||||
|
- if (0 != (retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info)))
|
||||||
|
- goto cleanup;
|
||||||
|
|
||||||
|
/* 2. Initialize a 32-bit, big-endian bit string counter as 1.
|
||||||
|
* 3. For i = 1 to reps by 1, do the following:
|
||||||
|
@@ -2450,7 +2430,7 @@ pkinit_alg_agility_kdf(krb5_context context,
|
||||||
|
|
||||||
|
ctx = EVP_MD_CTX_new();
|
||||||
|
if (ctx == NULL) {
|
||||||
|
- retval = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2458,7 +2438,7 @@ pkinit_alg_agility_kdf(krb5_context context,
|
||||||
|
if (!EVP_DigestInit(ctx, EVP_func())) {
|
||||||
|
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
|
||||||
|
"Call to OpenSSL EVP_DigestInit() returned an error.");
|
||||||
|
- retval = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2467,15 +2447,16 @@ pkinit_alg_agility_kdf(krb5_context context,
|
||||||
|
!EVP_DigestUpdate(ctx, other_info->data, other_info->length)) {
|
||||||
|
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
|
||||||
|
"Call to OpenSSL EVP_DigestUpdate() returned an error.");
|
||||||
|
- retval = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes. */
|
||||||
|
- if (!EVP_DigestFinal(ctx, (uint8_t *)random_data.data + offset, &s)) {
|
||||||
|
+ /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K
|
||||||
|
+ * bytes. */
|
||||||
|
+ if (!EVP_DigestFinal(ctx, (unsigned char *)out + offset, &s)) {
|
||||||
|
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
|
||||||
|
"Call to OpenSSL EVP_DigestUpdate() returned an error.");
|
||||||
|
- retval = KRB5_CRYPTO_INTERNAL;
|
||||||
|
+ ret = KRB5_CRYPTO_INTERNAL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
offset += s;
|
||||||
|
@@ -2484,26 +2465,113 @@ pkinit_alg_agility_kdf(krb5_context context,
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
ctx = NULL;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- retval = krb5_c_random_to_key(context, enctype, &random_data,
|
||||||
|
- key_block);
|
||||||
|
-
|
||||||
|
cleanup:
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
+ return ret;
|
||||||
|
+} /* builtin_sskdf() */
|
||||||
|
+#endif /* HAVE_EVP_KDF_FETCH */
|
||||||
|
|
||||||
|
- /* If this has been an error, free the allocated key_block, if any */
|
||||||
|
- if (retval) {
|
||||||
|
- krb5_free_keyblock_contents(context, key_block);
|
||||||
|
+/* id-pkinit-kdf family, as specified by RFC 8636. */
|
||||||
|
+krb5_error_code
|
||||||
|
+pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret,
|
||||||
|
+ krb5_data *alg_oid, krb5_const_principal party_u_info,
|
||||||
|
+ krb5_const_principal party_v_info,
|
||||||
|
+ krb5_enctype enctype, krb5_data *as_req,
|
||||||
|
+ krb5_data *pk_as_rep, krb5_keyblock *key_block)
|
||||||
|
+{
|
||||||
|
+ krb5_error_code ret;
|
||||||
|
+ size_t hash_len = 0, rand_len = 0, key_len = 0;
|
||||||
|
+ const EVP_MD *(*EVP_func)(void);
|
||||||
|
+ krb5_sp80056a_other_info other_info_fields;
|
||||||
|
+ krb5_pkinit_supp_pub_info supp_pub_info_fields;
|
||||||
|
+ krb5_data *other_info = NULL, *supp_pub_info = NULL;
|
||||||
|
+ krb5_data random_data = empty_data();
|
||||||
|
+ krb5_algorithm_identifier alg_id;
|
||||||
|
+ unsigned int reps;
|
||||||
|
+ char *hash_name = NULL;
|
||||||
|
+
|
||||||
|
+ /* Allocate and initialize the key block. */
|
||||||
|
+ key_block->magic = 0;
|
||||||
|
+ key_block->enctype = enctype;
|
||||||
|
+
|
||||||
|
+ /* Use separate variables to avoid alignment restriction problems. */
|
||||||
|
+ ret = krb5_c_keylengths(context, enctype, &rand_len, &key_len);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto cleanup;
|
||||||
|
+ random_data.length = rand_len;
|
||||||
|
+ key_block->length = key_len;
|
||||||
|
+
|
||||||
|
+ key_block->contents = k5calloc(key_block->length, 1, &ret);
|
||||||
|
+ if (key_block->contents == NULL)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ /* If this is anonymous pkinit, use the anonymous principle for
|
||||||
|
+ * party_u_info. */
|
||||||
|
+ if (party_u_info &&
|
||||||
|
+ krb5_principal_compare_any_realm(context, party_u_info,
|
||||||
|
+ krb5_anonymous_principal())) {
|
||||||
|
+ party_u_info = (krb5_principal)krb5_anonymous_principal();
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* free other allocated resources, either way */
|
||||||
|
- if (random_data.data)
|
||||||
|
- free(random_data.data);
|
||||||
|
+ ret = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func,
|
||||||
|
+ &hash_name);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ /* 1. reps = keydatalen (K) / hash length (H) */
|
||||||
|
+ reps = key_block->length / hash_len;
|
||||||
|
+
|
||||||
|
+ /* ... and round up, if necessary. */
|
||||||
|
+ if (key_block->length > (reps * hash_len))
|
||||||
|
+ reps++;
|
||||||
|
+
|
||||||
|
+ /* Allocate enough space in the random data buffer to hash directly into
|
||||||
|
+ * it, even if the last hash will make it bigger than the key length. */
|
||||||
|
+ random_data.data = k5alloc(reps * hash_len, &ret);
|
||||||
|
+ if (random_data.data == NULL)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ /* Encode the ASN.1 octet string for "SuppPubInfo". */
|
||||||
|
+ supp_pub_info_fields.enctype = enctype;
|
||||||
|
+ supp_pub_info_fields.as_req = *as_req;
|
||||||
|
+ supp_pub_info_fields.pk_as_rep = *pk_as_rep;
|
||||||
|
+ ret = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
|
||||||
|
+ &supp_pub_info);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ /* Now encode the ASN.1 octet string for "OtherInfo". */
|
||||||
|
+ memset(&alg_id, 0, sizeof(alg_id));
|
||||||
|
+ alg_id.algorithm = *alg_oid;
|
||||||
|
+ other_info_fields.algorithm_identifier = alg_id;
|
||||||
|
+ other_info_fields.party_u_info = (krb5_principal)party_u_info;
|
||||||
|
+ other_info_fields.party_v_info = (krb5_principal)party_v_info;
|
||||||
|
+ other_info_fields.supp_pub_info = *supp_pub_info;
|
||||||
|
+ ret = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_EVP_KDF_FETCH
|
||||||
|
+ ret = openssl_sskdf(context, hash_len, secret, other_info,
|
||||||
|
+ random_data.data, key_block->length, hash_name);
|
||||||
|
+#else
|
||||||
|
+ ret = builtin_sskdf(context, reps, hash_len, EVP_func, secret,
|
||||||
|
+ other_info, random_data.data, key_block->length);
|
||||||
|
+#endif
|
||||||
|
+ if (ret)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ ret = krb5_c_random_to_key(context, enctype, &random_data, key_block);
|
||||||
|
+cleanup:
|
||||||
|
+ if (ret)
|
||||||
|
+ krb5_free_keyblock_contents(context, key_block);
|
||||||
|
+
|
||||||
|
+ free(hash_name);
|
||||||
|
+ zapfree(random_data.data, random_data.length);
|
||||||
|
krb5_free_data(context, other_info);
|
||||||
|
krb5_free_data(context, supp_pub_info);
|
||||||
|
-
|
||||||
|
- return retval;
|
||||||
|
-} /*pkinit_alg_agility_kdf() */
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
|
||||||
|
/* Call DH_compute_key() and ensure that we left-pad short results instead of
|
||||||
|
* leaving junk bytes at the end of the buffer. */
|
|
@ -1,4 +1,4 @@
|
||||||
From 4a62aeae7b747cd289548949f940525365fe0947 Mon Sep 17 00:00:00 2001
|
From d2b050a5acfacd8d400560ae097f6d5f392d7398 Mon Sep 17 00:00:00 2001
|
||||||
From: Robbie Harwood <rharwood@redhat.com>
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
Date: Fri, 9 Nov 2018 15:12:21 -0500
|
Date: Fri, 9 Nov 2018 15:12:21 -0500
|
||||||
Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4
|
Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4
|
||||||
|
|
|
@ -1,752 +0,0 @@
|
||||||
From 687bb26cb0877fa5497e90f7d325de42b456da2a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Robbie Harwood <rharwood@redhat.com>
|
|
||||||
Date: Fri, 15 Nov 2019 20:05:16 +0000
|
|
||||||
Subject: [PATCH] [downstream] Use backported version of OpenSSL-3 KDF
|
|
||||||
interface
|
|
||||||
|
|
||||||
Last-updated: krb5-1.17
|
|
||||||
---
|
|
||||||
src/configure.ac | 4 +
|
|
||||||
src/lib/crypto/krb/derive.c | 356 +++++++++++++-----
|
|
||||||
.../preauth/pkinit/pkinit_crypto_openssl.c | 257 ++++++++-----
|
|
||||||
3 files changed, 428 insertions(+), 189 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/configure.ac b/src/configure.ac
|
|
||||||
index 3e1052db7..ea708491b 100644
|
|
||||||
--- a/src/configure.ac
|
|
||||||
+++ b/src/configure.ac
|
|
||||||
@@ -282,6 +282,10 @@ AC_SUBST(CRYPTO_IMPL)
|
|
||||||
AC_SUBST(CRYPTO_IMPL_CFLAGS)
|
|
||||||
AC_SUBST(CRYPTO_IMPL_LIBS)
|
|
||||||
|
|
||||||
+AC_CHECK_FUNCS(EVP_KDF_CTX_new_id EVP_KDF_ctrl EVP_KDF_derive,
|
|
||||||
+ AC_DEFINE(OSSL_KDFS, 1, [Define if using OpenSSL KDFs]),
|
|
||||||
+ AC_MSG_ERROR([backported OpenSSL KDFs not found]))
|
|
||||||
+
|
|
||||||
AC_ARG_WITH([prng-alg],
|
|
||||||
AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]),
|
|
||||||
[PRNG_ALG=$withval
|
|
||||||
diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
|
|
||||||
index 6707a7308..915a173dd 100644
|
|
||||||
--- a/src/lib/crypto/krb/derive.c
|
|
||||||
+++ b/src/lib/crypto/krb/derive.c
|
|
||||||
@@ -27,6 +27,13 @@
|
|
||||||
|
|
||||||
#include "crypto_int.h"
|
|
||||||
|
|
||||||
+#ifdef OSSL_KDFS
|
|
||||||
+#include <openssl/evp.h>
|
|
||||||
+#include <openssl/kdf.h>
|
|
||||||
+#else
|
|
||||||
+#error "Refusing to build without OpenSSL KDFs!"
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
static krb5_key
|
|
||||||
find_cached_dkey(struct derived_key *list, const krb5_data *constant)
|
|
||||||
{
|
|
||||||
@@ -77,55 +84,193 @@ cleanup:
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef OSSL_KDFS
|
|
||||||
static krb5_error_code
|
|
||||||
-derive_random_rfc3961(const struct krb5_enc_provider *enc,
|
|
||||||
- krb5_key inkey, krb5_data *outrnd,
|
|
||||||
- const krb5_data *in_constant)
|
|
||||||
+openssl_kbdkf_counter_hmac(const struct krb5_hash_provider *hash,
|
|
||||||
+ krb5_key inkey, krb5_data *outrnd,
|
|
||||||
+ const krb5_data *label, const krb5_data *context)
|
|
||||||
{
|
|
||||||
- size_t blocksize, keybytes, n;
|
|
||||||
+ krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
|
|
||||||
+ EVP_KDF_CTX *ctx = NULL;
|
|
||||||
+ const EVP_MD *digest;
|
|
||||||
+
|
|
||||||
+ if (!strcmp(hash->hash_name, "SHA1"))
|
|
||||||
+ digest = EVP_sha1();
|
|
||||||
+ else if (!strcmp(hash->hash_name, "SHA-256"))
|
|
||||||
+ digest = EVP_sha256();
|
|
||||||
+ else if (!strcmp(hash->hash_name, "SHA-384"))
|
|
||||||
+ digest = EVP_sha384();
|
|
||||||
+ else
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB);
|
|
||||||
+ if (!ctx)
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
|
|
||||||
+ EVP_KDF_KB_MAC_TYPE_HMAC) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
|
|
||||||
+ inkey->keyblock.length) != 1 ||
|
|
||||||
+ (context->length > 0 &&
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_INFO, context->data,
|
|
||||||
+ context->length) != 1) ||
|
|
||||||
+ (label->length > 0 &&
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, label->data,
|
|
||||||
+ label->length) != 1) ||
|
|
||||||
+ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
|
|
||||||
+ outrnd->length) != 1)
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ ret = 0;
|
|
||||||
+done:
|
|
||||||
+ if (ret)
|
|
||||||
+ zap(outrnd->data, outrnd->length);
|
|
||||||
+ EVP_KDF_CTX_free(ctx);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static krb5_error_code
|
|
||||||
+openssl_kbkdf_feedback_cmac(const struct krb5_enc_provider *enc,
|
|
||||||
+ krb5_key inkey, krb5_data *outrnd,
|
|
||||||
+ const krb5_data *in_constant)
|
|
||||||
+{
|
|
||||||
+ krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
|
|
||||||
+ EVP_KDF_CTX *ctx = NULL;
|
|
||||||
+ const EVP_CIPHER *cipher;
|
|
||||||
+ static unsigned char zeroes[16];
|
|
||||||
+
|
|
||||||
+ memset(zeroes, 0, sizeof(zeroes));
|
|
||||||
+
|
|
||||||
+ if (enc->keylength == 16)
|
|
||||||
+ cipher = EVP_camellia_128_cbc();
|
|
||||||
+ else if (enc->keylength == 32)
|
|
||||||
+ cipher = EVP_camellia_256_cbc();
|
|
||||||
+ else
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB);
|
|
||||||
+ if (!ctx)
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MODE,
|
|
||||||
+ EVP_KDF_KB_MODE_FEEDBACK) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
|
|
||||||
+ EVP_KDF_KB_MAC_TYPE_CMAC) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
|
|
||||||
+ inkey->keyblock.length) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, in_constant->data,
|
|
||||||
+ in_constant->length) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_SEED, zeroes,
|
|
||||||
+ sizeof(zeroes)) != 1 ||
|
|
||||||
+ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
|
|
||||||
+ outrnd->length) != 1)
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ ret = 0;
|
|
||||||
+done:
|
|
||||||
+ if (ret)
|
|
||||||
+ zap(outrnd->data, outrnd->length);
|
|
||||||
+ EVP_KDF_CTX_free(ctx);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static krb5_error_code
|
|
||||||
+openssl_krb5kdf(const struct krb5_enc_provider *enc, krb5_key inkey,
|
|
||||||
+ krb5_data *outrnd, const krb5_data *in_constant)
|
|
||||||
+{
|
|
||||||
+ krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
|
|
||||||
+ EVP_KDF_CTX *ctx = NULL;
|
|
||||||
+ const EVP_CIPHER *cipher;
|
|
||||||
+
|
|
||||||
+ if (inkey->keyblock.length != enc->keylength ||
|
|
||||||
+ outrnd->length != enc->keybytes) {
|
|
||||||
+ return KRB5_CRYPTO_INTERNAL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 16)
|
|
||||||
+ cipher = EVP_aes_128_cbc();
|
|
||||||
+ else if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 32)
|
|
||||||
+ cipher = EVP_aes_256_cbc();
|
|
||||||
+ else if (enc->keylength == 24)
|
|
||||||
+ cipher = EVP_des_ede3_cbc();
|
|
||||||
+ else
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KRB5KDF);
|
|
||||||
+ if (ctx == NULL)
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
|
|
||||||
+ inkey->keyblock.length) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT,
|
|
||||||
+ in_constant->data, in_constant->length) != 1 ||
|
|
||||||
+ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
|
|
||||||
+ outrnd->length) != 1)
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ ret = 0;
|
|
||||||
+done:
|
|
||||||
+ if (ret)
|
|
||||||
+ zap(outrnd->data, outrnd->length);
|
|
||||||
+ EVP_KDF_CTX_free(ctx);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#else /* OSSL_KDFS */
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * NIST SP800-108 KDF in counter mode (section 5.1).
|
|
||||||
+ * Parameters:
|
|
||||||
+ * - HMAC (with hash as the hash provider) is the PRF.
|
|
||||||
+ * - A block counter of four bytes is used.
|
|
||||||
+ * - Four bytes are used to encode the output length in the PRF input.
|
|
||||||
+ *
|
|
||||||
+ * There are no uses requiring more than a single PRF invocation.
|
|
||||||
+ */
|
|
||||||
+static krb5_error_code
|
|
||||||
+builtin_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
|
|
||||||
+ krb5_key inkey, krb5_data *outrnd,
|
|
||||||
+ const krb5_data *label,
|
|
||||||
+ const krb5_data *context)
|
|
||||||
+{
|
|
||||||
+ krb5_crypto_iov iov[5];
|
|
||||||
krb5_error_code ret;
|
|
||||||
- krb5_data block = empty_data();
|
|
||||||
+ krb5_data prf;
|
|
||||||
+ unsigned char ibuf[4], lbuf[4];
|
|
||||||
|
|
||||||
- blocksize = enc->block_size;
|
|
||||||
- keybytes = enc->keybytes;
|
|
||||||
-
|
|
||||||
- if (blocksize == 1)
|
|
||||||
- return KRB5_BAD_ENCTYPE;
|
|
||||||
- if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
|
|
||||||
+ if (hash == NULL || outrnd->length > hash->hashsize)
|
|
||||||
return KRB5_CRYPTO_INTERNAL;
|
|
||||||
|
|
||||||
/* Allocate encryption data buffer. */
|
|
||||||
- ret = alloc_data(&block, blocksize);
|
|
||||||
+ ret = alloc_data(&prf, hash->hashsize);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
- /* Initialize the input block. */
|
|
||||||
- if (in_constant->length == blocksize) {
|
|
||||||
- memcpy(block.data, in_constant->data, blocksize);
|
|
||||||
- } else {
|
|
||||||
- krb5int_nfold(in_constant->length * 8,
|
|
||||||
- (unsigned char *) in_constant->data,
|
|
||||||
- blocksize * 8, (unsigned char *) block.data);
|
|
||||||
- }
|
|
||||||
+ /* [i]2: four-byte big-endian binary string giving the block counter (1) */
|
|
||||||
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
+ iov[0].data = make_data(ibuf, sizeof(ibuf));
|
|
||||||
+ store_32_be(1, ibuf);
|
|
||||||
+ /* Label */
|
|
||||||
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
+ iov[1].data = *label;
|
|
||||||
+ /* 0x00: separator byte */
|
|
||||||
+ iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
+ iov[2].data = make_data("", 1);
|
|
||||||
+ /* Context */
|
|
||||||
+ iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
+ iov[3].data = *context;
|
|
||||||
+ /* [L]2: four-byte big-endian binary string giving the output length */
|
|
||||||
+ iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
+ iov[4].data = make_data(lbuf, sizeof(lbuf));
|
|
||||||
+ store_32_be(outrnd->length * 8, lbuf);
|
|
||||||
|
|
||||||
- /* Loop encrypting the blocks until enough key bytes are generated. */
|
|
||||||
- n = 0;
|
|
||||||
- while (n < keybytes) {
|
|
||||||
- ret = encrypt_block(enc, inkey, &block);
|
|
||||||
- if (ret)
|
|
||||||
- goto cleanup;
|
|
||||||
-
|
|
||||||
- if ((keybytes - n) <= blocksize) {
|
|
||||||
- memcpy(outrnd->data + n, block.data, (keybytes - n));
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- memcpy(outrnd->data + n, block.data, blocksize);
|
|
||||||
- n += blocksize;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
-cleanup:
|
|
||||||
- zapfree(block.data, blocksize);
|
|
||||||
+ ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
|
|
||||||
+ if (!ret)
|
|
||||||
+ memcpy(outrnd->data, prf.data, outrnd->length);
|
|
||||||
+ zapfree(prf.data, prf.length);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -139,9 +284,9 @@ cleanup:
|
|
||||||
* - Four bytes are used to encode the output length in the PRF input.
|
|
||||||
*/
|
|
||||||
static krb5_error_code
|
|
||||||
-derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
|
|
||||||
- krb5_key inkey, krb5_data *outrnd,
|
|
||||||
- const krb5_data *in_constant)
|
|
||||||
+builtin_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
|
|
||||||
+ krb5_key inkey, krb5_data *outrnd,
|
|
||||||
+ const krb5_data *in_constant)
|
|
||||||
{
|
|
||||||
size_t blocksize, keybytes, n;
|
|
||||||
krb5_crypto_iov iov[6];
|
|
||||||
@@ -204,56 +349,94 @@ cleanup:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/*
|
|
||||||
- * NIST SP800-108 KDF in counter mode (section 5.1).
|
|
||||||
- * Parameters:
|
|
||||||
- * - HMAC (with hash as the hash provider) is the PRF.
|
|
||||||
- * - A block counter of four bytes is used.
|
|
||||||
- * - Four bytes are used to encode the output length in the PRF input.
|
|
||||||
- *
|
|
||||||
- * There are no uses requiring more than a single PRF invocation.
|
|
||||||
- */
|
|
||||||
+static krb5_error_code
|
|
||||||
+builtin_derive_random_rfc3961(const struct krb5_enc_provider *enc,
|
|
||||||
+ krb5_key inkey, krb5_data *outrnd,
|
|
||||||
+ const krb5_data *in_constant)
|
|
||||||
+{
|
|
||||||
+ size_t blocksize, keybytes, n;
|
|
||||||
+ krb5_error_code ret;
|
|
||||||
+ krb5_data block = empty_data();
|
|
||||||
+
|
|
||||||
+ blocksize = enc->block_size;
|
|
||||||
+ keybytes = enc->keybytes;
|
|
||||||
+
|
|
||||||
+ if (blocksize == 1)
|
|
||||||
+ return KRB5_BAD_ENCTYPE;
|
|
||||||
+ if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
|
|
||||||
+ return KRB5_CRYPTO_INTERNAL;
|
|
||||||
+
|
|
||||||
+ /* Allocate encryption data buffer. */
|
|
||||||
+ ret = alloc_data(&block, blocksize);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ /* Initialize the input block. */
|
|
||||||
+ if (in_constant->length == blocksize) {
|
|
||||||
+ memcpy(block.data, in_constant->data, blocksize);
|
|
||||||
+ } else {
|
|
||||||
+ krb5int_nfold(in_constant->length * 8,
|
|
||||||
+ (unsigned char *) in_constant->data,
|
|
||||||
+ blocksize * 8, (unsigned char *) block.data);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Loop encrypting the blocks until enough key bytes are generated. */
|
|
||||||
+ n = 0;
|
|
||||||
+ while (n < keybytes) {
|
|
||||||
+ ret = encrypt_block(enc, inkey, &block);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ if ((keybytes - n) <= blocksize) {
|
|
||||||
+ memcpy(outrnd->data + n, block.data, (keybytes - n));
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ memcpy(outrnd->data + n, block.data, blocksize);
|
|
||||||
+ n += blocksize;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+cleanup:
|
|
||||||
+ zapfree(block.data, blocksize);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+#endif /* OSSL_KDFS */
|
|
||||||
+
|
|
||||||
krb5_error_code
|
|
||||||
k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
|
|
||||||
krb5_key inkey, krb5_data *outrnd,
|
|
||||||
const krb5_data *label, const krb5_data *context)
|
|
||||||
{
|
|
||||||
- krb5_crypto_iov iov[5];
|
|
||||||
- krb5_error_code ret;
|
|
||||||
- krb5_data prf;
|
|
||||||
- unsigned char ibuf[4], lbuf[4];
|
|
||||||
+#ifdef OSSL_KDFS
|
|
||||||
+ return openssl_kbdkf_counter_hmac(hash, inkey, outrnd, label, context);
|
|
||||||
+#else
|
|
||||||
+ return builtin_sp800_108_counter_hmac(hash, inkey, outrnd, label,
|
|
||||||
+ context);
|
|
||||||
+#endif
|
|
||||||
+}
|
|
||||||
|
|
||||||
- if (hash == NULL || outrnd->length > hash->hashsize)
|
|
||||||
- return KRB5_CRYPTO_INTERNAL;
|
|
||||||
+static krb5_error_code
|
|
||||||
+k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
|
|
||||||
+ krb5_key inkey, krb5_data *outrnd,
|
|
||||||
+ const krb5_data *in_constant)
|
|
||||||
+{
|
|
||||||
+#ifdef OSSL_KDFS
|
|
||||||
+ return openssl_kbkdf_feedback_cmac(enc, inkey, outrnd, in_constant);
|
|
||||||
+#else
|
|
||||||
+ return builtin_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
|
|
||||||
+#endif
|
|
||||||
+}
|
|
||||||
|
|
||||||
- /* Allocate encryption data buffer. */
|
|
||||||
- ret = alloc_data(&prf, hash->hashsize);
|
|
||||||
- if (ret)
|
|
||||||
- return ret;
|
|
||||||
-
|
|
||||||
- /* [i]2: four-byte big-endian binary string giving the block counter (1) */
|
|
||||||
- iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
- iov[0].data = make_data(ibuf, sizeof(ibuf));
|
|
||||||
- store_32_be(1, ibuf);
|
|
||||||
- /* Label */
|
|
||||||
- iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
- iov[1].data = *label;
|
|
||||||
- /* 0x00: separator byte */
|
|
||||||
- iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
- iov[2].data = make_data("", 1);
|
|
||||||
- /* Context */
|
|
||||||
- iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
- iov[3].data = *context;
|
|
||||||
- /* [L]2: four-byte big-endian binary string giving the output length */
|
|
||||||
- iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
||||||
- iov[4].data = make_data(lbuf, sizeof(lbuf));
|
|
||||||
- store_32_be(outrnd->length * 8, lbuf);
|
|
||||||
-
|
|
||||||
- ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
|
|
||||||
- if (!ret)
|
|
||||||
- memcpy(outrnd->data, prf.data, outrnd->length);
|
|
||||||
- zapfree(prf.data, prf.length);
|
|
||||||
- return ret;
|
|
||||||
+static krb5_error_code
|
|
||||||
+k5_derive_random_rfc3961(const struct krb5_enc_provider *enc,
|
|
||||||
+ krb5_key inkey, krb5_data *outrnd,
|
|
||||||
+ const krb5_data *in_constant)
|
|
||||||
+{
|
|
||||||
+#ifdef OSSL_KDFS
|
|
||||||
+ return openssl_krb5kdf(enc, inkey, outrnd, in_constant);
|
|
||||||
+#else
|
|
||||||
+ return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
|
|
||||||
+#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
krb5_error_code
|
|
||||||
@@ -266,10 +449,9 @@ krb5int_derive_random(const struct krb5_enc_provider *enc,
|
|
||||||
|
|
||||||
switch (alg) {
|
|
||||||
case DERIVE_RFC3961:
|
|
||||||
- return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
|
|
||||||
+ return k5_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
|
|
||||||
case DERIVE_SP800_108_CMAC:
|
|
||||||
- return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd,
|
|
||||||
- in_constant);
|
|
||||||
+ return k5_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
|
|
||||||
case DERIVE_SP800_108_HMAC:
|
|
||||||
return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant,
|
|
||||||
&empty);
|
|
||||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
||||||
index e1153344e..911e74fd9 100644
|
|
||||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
||||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
||||||
@@ -38,6 +38,13 @@
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
+#ifdef OSSL_KDFS
|
|
||||||
+#include <openssl/evp.h>
|
|
||||||
+#include <openssl/kdf.h>
|
|
||||||
+#else
|
|
||||||
+#error "Refusing to build without OpenSSL KDFs!"
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
|
|
||||||
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
|
|
||||||
|
|
||||||
@@ -2331,11 +2338,51 @@ pkinit_alg_values(krb5_context context,
|
|
||||||
}
|
|
||||||
} /* pkinit_alg_values() */
|
|
||||||
|
|
||||||
+#ifdef OSSL_KDFS
|
|
||||||
+static krb5_error_code
|
|
||||||
+openssl_sskdf(krb5_context context, size_t hash_bytes, krb5_data *key,
|
|
||||||
+ krb5_data *info, char *out, size_t out_len)
|
|
||||||
+{
|
|
||||||
+ krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
|
|
||||||
+ EVP_KDF_CTX *ctx = NULL;
|
|
||||||
+ const EVP_MD *digest;
|
|
||||||
|
|
||||||
-/* pkinit_alg_agility_kdf() --
|
|
||||||
- * This function generates a key using the KDF described in
|
|
||||||
- * draft_ietf_krb_wg_pkinit_alg_agility-04.txt. The algorithm is
|
|
||||||
- * described as follows:
|
|
||||||
+ /* RFC 8636 defines a SHA384 variant, but we don't use it. */
|
|
||||||
+ if (hash_bytes == 20) {
|
|
||||||
+ digest = EVP_sha1();
|
|
||||||
+ } else if (hash_bytes == 32) {
|
|
||||||
+ digest = EVP_sha256();
|
|
||||||
+ } else if (hash_bytes == 64) {
|
|
||||||
+ digest = EVP_sha512();
|
|
||||||
+ } else {
|
|
||||||
+ krb5_set_error_message(context, ret, "Bad hash type for SSKDF");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
|
|
||||||
+ if (!ctx) {
|
|
||||||
+ oerr(context, ret, _("Failed to instantiate SSKDF"));
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key->data,
|
|
||||||
+ key->length) != 1 ||
|
|
||||||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSKDF_INFO, info->data,
|
|
||||||
+ info->length) != 1 ||
|
|
||||||
+ EVP_KDF_derive(ctx, (unsigned char *)out, out_len) != 1)
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ ret = 0;
|
|
||||||
+done:
|
|
||||||
+ EVP_KDF_CTX_free(ctx);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+/*
|
|
||||||
+ * Generate a key using the KDF described in RFC 8636, also known as SSKDF
|
|
||||||
+ * (single-step kdf). Our caller precomputes `reps`, but otherwise the
|
|
||||||
+ * algorithm is as follows:
|
|
||||||
*
|
|
||||||
* 1. reps = keydatalen (K) / hash length (H)
|
|
||||||
*
|
|
||||||
@@ -2349,95 +2396,16 @@ pkinit_alg_values(krb5_context context,
|
|
||||||
*
|
|
||||||
* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes.
|
|
||||||
*/
|
|
||||||
-krb5_error_code
|
|
||||||
-pkinit_alg_agility_kdf(krb5_context context,
|
|
||||||
- krb5_data *secret,
|
|
||||||
- krb5_data *alg_oid,
|
|
||||||
- krb5_const_principal party_u_info,
|
|
||||||
- krb5_const_principal party_v_info,
|
|
||||||
- krb5_enctype enctype,
|
|
||||||
- krb5_data *as_req,
|
|
||||||
- krb5_data *pk_as_rep,
|
|
||||||
- krb5_keyblock *key_block)
|
|
||||||
+static krb5_error_code
|
|
||||||
+builtin_sskdf(krb5_context context, unsigned int reps, size_t hash_len,
|
|
||||||
+ const EVP_MD *(*EVP_func)(void), krb5_data *secret,
|
|
||||||
+ krb5_data *other_info, char *out, size_t out_len)
|
|
||||||
{
|
|
||||||
krb5_error_code retval = 0;
|
|
||||||
|
|
||||||
- unsigned int reps = 0;
|
|
||||||
- uint32_t counter = 1; /* Does this type work on Windows? */
|
|
||||||
+ uint32_t counter = 1;
|
|
||||||
size_t offset = 0;
|
|
||||||
- size_t hash_len = 0;
|
|
||||||
- size_t rand_len = 0;
|
|
||||||
- size_t key_len = 0;
|
|
||||||
- krb5_data random_data;
|
|
||||||
- krb5_sp80056a_other_info other_info_fields;
|
|
||||||
- krb5_pkinit_supp_pub_info supp_pub_info_fields;
|
|
||||||
- krb5_data *other_info = NULL;
|
|
||||||
- krb5_data *supp_pub_info = NULL;
|
|
||||||
- krb5_algorithm_identifier alg_id;
|
|
||||||
EVP_MD_CTX *ctx = NULL;
|
|
||||||
- const EVP_MD *(*EVP_func)(void);
|
|
||||||
-
|
|
||||||
- /* initialize random_data here to make clean-up safe */
|
|
||||||
- random_data.length = 0;
|
|
||||||
- random_data.data = NULL;
|
|
||||||
-
|
|
||||||
- /* allocate and initialize the key block */
|
|
||||||
- key_block->magic = 0;
|
|
||||||
- key_block->enctype = enctype;
|
|
||||||
- if (0 != (retval = krb5_c_keylengths(context, enctype, &rand_len,
|
|
||||||
- &key_len)))
|
|
||||||
- goto cleanup;
|
|
||||||
-
|
|
||||||
- random_data.length = rand_len;
|
|
||||||
- key_block->length = key_len;
|
|
||||||
-
|
|
||||||
- if (NULL == (key_block->contents = malloc(key_block->length))) {
|
|
||||||
- retval = ENOMEM;
|
|
||||||
- goto cleanup;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- memset (key_block->contents, 0, key_block->length);
|
|
||||||
-
|
|
||||||
- /* If this is anonymous pkinit, use the anonymous principle for party_u_info */
|
|
||||||
- if (party_u_info && krb5_principal_compare_any_realm(context, party_u_info,
|
|
||||||
- krb5_anonymous_principal()))
|
|
||||||
- party_u_info = (krb5_principal)krb5_anonymous_principal();
|
|
||||||
-
|
|
||||||
- if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func)))
|
|
||||||
- goto cleanup;
|
|
||||||
-
|
|
||||||
- /* 1. reps = keydatalen (K) / hash length (H) */
|
|
||||||
- reps = key_block->length/hash_len;
|
|
||||||
-
|
|
||||||
- /* ... and round up, if necessary */
|
|
||||||
- if (key_block->length > (reps * hash_len))
|
|
||||||
- reps++;
|
|
||||||
-
|
|
||||||
- /* Allocate enough space in the random data buffer to hash directly into
|
|
||||||
- * it, even if the last hash will make it bigger than the key length. */
|
|
||||||
- if (NULL == (random_data.data = malloc(reps * hash_len))) {
|
|
||||||
- retval = ENOMEM;
|
|
||||||
- goto cleanup;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* Encode the ASN.1 octet string for "SuppPubInfo" */
|
|
||||||
- supp_pub_info_fields.enctype = enctype;
|
|
||||||
- supp_pub_info_fields.as_req = *as_req;
|
|
||||||
- supp_pub_info_fields.pk_as_rep = *pk_as_rep;
|
|
||||||
- if (0 != ((retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
|
|
||||||
- &supp_pub_info))))
|
|
||||||
- goto cleanup;
|
|
||||||
-
|
|
||||||
- /* Now encode the ASN.1 octet string for "OtherInfo" */
|
|
||||||
- memset(&alg_id, 0, sizeof alg_id);
|
|
||||||
- alg_id.algorithm = *alg_oid; /*alias*/
|
|
||||||
-
|
|
||||||
- other_info_fields.algorithm_identifier = alg_id;
|
|
||||||
- other_info_fields.party_u_info = (krb5_principal) party_u_info;
|
|
||||||
- other_info_fields.party_v_info = (krb5_principal) party_v_info;
|
|
||||||
- other_info_fields.supp_pub_info = *supp_pub_info;
|
|
||||||
- if (0 != (retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info)))
|
|
||||||
- goto cleanup;
|
|
||||||
|
|
||||||
/* 2. Initialize a 32-bit, big-endian bit string counter as 1.
|
|
||||||
* 3. For i = 1 to reps by 1, do the following:
|
|
||||||
@@ -2471,8 +2439,9 @@ pkinit_alg_agility_kdf(krb5_context context,
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes. */
|
|
||||||
- if (!EVP_DigestFinal(ctx, (uint8_t *)random_data.data + offset, &s)) {
|
|
||||||
+ /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K
|
|
||||||
+ * bytes. */
|
|
||||||
+ if (!EVP_DigestFinal(ctx, (unsigned char *)out + offset, &s)) {
|
|
||||||
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
|
|
||||||
"Call to OpenSSL EVP_DigestUpdate() returned an error.");
|
|
||||||
retval = KRB5_CRYPTO_INTERNAL;
|
|
||||||
@@ -2484,26 +2453,110 @@ pkinit_alg_agility_kdf(krb5_context context,
|
|
||||||
EVP_MD_CTX_free(ctx);
|
|
||||||
ctx = NULL;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- retval = krb5_c_random_to_key(context, enctype, &random_data,
|
|
||||||
- key_block);
|
|
||||||
-
|
|
||||||
cleanup:
|
|
||||||
EVP_MD_CTX_free(ctx);
|
|
||||||
+ return retval;
|
|
||||||
+} /* builtin_sskdf() */
|
|
||||||
+#endif /* OSSL_KDFS */
|
|
||||||
|
|
||||||
- /* If this has been an error, free the allocated key_block, if any */
|
|
||||||
- if (retval) {
|
|
||||||
- krb5_free_keyblock_contents(context, key_block);
|
|
||||||
+/* id-pkinit-kdf family, as specified by RFC 8636. */
|
|
||||||
+krb5_error_code
|
|
||||||
+pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret,
|
|
||||||
+ krb5_data *alg_oid, krb5_const_principal party_u_info,
|
|
||||||
+ krb5_const_principal party_v_info,
|
|
||||||
+ krb5_enctype enctype, krb5_data *as_req,
|
|
||||||
+ krb5_data *pk_as_rep, krb5_keyblock *key_block)
|
|
||||||
+{
|
|
||||||
+ krb5_error_code retval;
|
|
||||||
+ size_t hash_len = 0, rand_len = 0, key_len = 0;
|
|
||||||
+ const EVP_MD *(*EVP_func)(void);
|
|
||||||
+ krb5_sp80056a_other_info other_info_fields;
|
|
||||||
+ krb5_pkinit_supp_pub_info supp_pub_info_fields;
|
|
||||||
+ krb5_data *other_info = NULL, *supp_pub_info = NULL;
|
|
||||||
+ krb5_data random_data = empty_data();
|
|
||||||
+ krb5_algorithm_identifier alg_id;
|
|
||||||
+ unsigned int reps;
|
|
||||||
+
|
|
||||||
+ /* Allocate and initialize the key block. */
|
|
||||||
+ key_block->magic = 0;
|
|
||||||
+ key_block->enctype = enctype;
|
|
||||||
+
|
|
||||||
+ /* Use separate variables to avoid alignment restriction problems. */
|
|
||||||
+ retval = krb5_c_keylengths(context, enctype, &rand_len, &key_len);
|
|
||||||
+ if (retval)
|
|
||||||
+ goto cleanup;
|
|
||||||
+ random_data.length = rand_len;
|
|
||||||
+ key_block->length = key_len;
|
|
||||||
+
|
|
||||||
+ key_block->contents = k5calloc(key_block->length, 1, &retval);
|
|
||||||
+ if (key_block->contents == NULL)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ /* If this is anonymous pkinit, use the anonymous principle for
|
|
||||||
+ * party_u_info. */
|
|
||||||
+ if (party_u_info &&
|
|
||||||
+ krb5_principal_compare_any_realm(context, party_u_info,
|
|
||||||
+ krb5_anonymous_principal())) {
|
|
||||||
+ party_u_info = (krb5_principal)krb5_anonymous_principal();
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* free other allocated resources, either way */
|
|
||||||
- if (random_data.data)
|
|
||||||
- free(random_data.data);
|
|
||||||
+ retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func);
|
|
||||||
+ if (retval)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ /* 1. reps = keydatalen (K) / hash length (H) */
|
|
||||||
+ reps = key_block->length / hash_len;
|
|
||||||
+
|
|
||||||
+ /* ... and round up, if necessary. */
|
|
||||||
+ if (key_block->length > (reps * hash_len))
|
|
||||||
+ reps++;
|
|
||||||
+
|
|
||||||
+ /* Allocate enough space in the random data buffer to hash directly into
|
|
||||||
+ * it, even if the last hash will make it bigger than the key length. */
|
|
||||||
+ random_data.data = k5alloc(reps * hash_len, &retval);
|
|
||||||
+ if (random_data.data == NULL)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ /* Encode the ASN.1 octet string for "SuppPubInfo". */
|
|
||||||
+ supp_pub_info_fields.enctype = enctype;
|
|
||||||
+ supp_pub_info_fields.as_req = *as_req;
|
|
||||||
+ supp_pub_info_fields.pk_as_rep = *pk_as_rep;
|
|
||||||
+ retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
|
|
||||||
+ &supp_pub_info);
|
|
||||||
+ if (retval)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ /* Now encode the ASN.1 octet string for "OtherInfo". */
|
|
||||||
+ memset(&alg_id, 0, sizeof(alg_id));
|
|
||||||
+ alg_id.algorithm = *alg_oid;
|
|
||||||
+ other_info_fields.algorithm_identifier = alg_id;
|
|
||||||
+ other_info_fields.party_u_info = (krb5_principal)party_u_info;
|
|
||||||
+ other_info_fields.party_v_info = (krb5_principal)party_v_info;
|
|
||||||
+ other_info_fields.supp_pub_info = *supp_pub_info;
|
|
||||||
+ retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info);
|
|
||||||
+ if (retval)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+#ifdef OSSL_KDFS
|
|
||||||
+ retval = openssl_sskdf(context, hash_len, secret, other_info,
|
|
||||||
+ random_data.data, key_block->length);
|
|
||||||
+#else
|
|
||||||
+ retval = builtin_sskdf(context, reps, hash_len, EVP_func, secret,
|
|
||||||
+ other_info, random_data.data, key_block->length);
|
|
||||||
+#endif
|
|
||||||
+ if (retval)
|
|
||||||
+ goto cleanup;
|
|
||||||
+
|
|
||||||
+ retval = krb5_c_random_to_key(context, enctype, &random_data, key_block);
|
|
||||||
+cleanup:
|
|
||||||
+ if (retval)
|
|
||||||
+ krb5_free_keyblock_contents(context, key_block);
|
|
||||||
+
|
|
||||||
+ zapfree(random_data.data, random_data.length);
|
|
||||||
krb5_free_data(context, other_info);
|
|
||||||
krb5_free_data(context, supp_pub_info);
|
|
||||||
-
|
|
||||||
return retval;
|
|
||||||
-} /*pkinit_alg_agility_kdf() */
|
|
||||||
+}
|
|
||||||
|
|
||||||
/* Call DH_compute_key() and ensure that we left-pad short results instead of
|
|
||||||
* leaving junk bytes at the end of the buffer. */
|
|
21
krb5.spec
21
krb5.spec
|
@ -42,7 +42,7 @@
|
||||||
Summary: The Kerberos network authentication system
|
Summary: The Kerberos network authentication system
|
||||||
Name: krb5
|
Name: krb5
|
||||||
Version: 1.19.1
|
Version: 1.19.1
|
||||||
Release: %{?zdpd}3%{?dist}.1
|
Release: %{?zdpd}4%{?dist}
|
||||||
|
|
||||||
# rharwood has trust path to signing key and verifies on check-in
|
# rharwood has trust path to signing key and verifies on check-in
|
||||||
Source0: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz
|
Source0: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz
|
||||||
|
@ -68,11 +68,17 @@ Patch1: downstream-SELinux-integration.patch
|
||||||
Patch3: downstream-netlib-and-dns.patch
|
Patch3: downstream-netlib-and-dns.patch
|
||||||
Patch4: downstream-fix-debuginfo-with-y.tab.c.patch
|
Patch4: downstream-fix-debuginfo-with-y.tab.c.patch
|
||||||
Patch5: downstream-Remove-3des-support.patch
|
Patch5: downstream-Remove-3des-support.patch
|
||||||
Patch6: downstream-Use-backported-version-of-OpenSSL-3-KDF-i.patch
|
|
||||||
Patch7: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
|
Patch7: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
|
||||||
Patch8: Add-APIs-for-marshalling-credentials.patch
|
Patch8: Add-APIs-for-marshalling-credentials.patch
|
||||||
Patch9: Add-hostname-canonicalization-helper-to-k5test.py.patch
|
Patch9: Add-hostname-canonicalization-helper-to-k5test.py.patch
|
||||||
Patch10: Support-host-based-GSS-initiator-names.patch
|
Patch10: Support-host-based-GSS-initiator-names.patch
|
||||||
|
Patch11: Fix-softpkcs11-build-issues-with-openssl-3.0.patch
|
||||||
|
Patch12: softpkcs11-Remove-all-openssl-deprecated-functions.patch
|
||||||
|
Patch13: Add-buildsystem-detection-of-the-OpenSSL-3-KDF-inter.patch
|
||||||
|
Patch14: Use-OpenSSL-s-SSKDF-in-PKINIT-when-available.patch
|
||||||
|
Patch15: Use-OpenSSL-s-KBKDF-and-KRB5KDF-for-deriving-long-te.patch
|
||||||
|
Patch16: Handle-OpenSSL-3-s-providers.patch
|
||||||
|
Patch17: Handle-SSL_read-changed-behavior-on-server-hangup.patch
|
||||||
|
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: https://web.mit.edu/kerberos/www/
|
URL: https://web.mit.edu/kerberos/www/
|
||||||
|
@ -103,9 +109,8 @@ BuildRequires: iproute
|
||||||
BuildRequires: python3-pyrad
|
BuildRequires: python3-pyrad
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
# Need KDFs. This is the backported version
|
# Need KDFs. This is the "real" version
|
||||||
BuildRequires: openssl-devel >= 1:1.1.1d-4
|
BuildRequires: openssl-devel >= 1:3.0.0
|
||||||
BuildRequires: openssl-devel < 1:3.0.0
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Kerberos V5 is a trusted-third-party network authentication system,
|
Kerberos V5 is a trusted-third-party network authentication system,
|
||||||
|
@ -131,7 +136,7 @@ to install this package.
|
||||||
|
|
||||||
%package libs
|
%package libs
|
||||||
Summary: The non-admin shared libraries used by Kerberos 5
|
Summary: The non-admin shared libraries used by Kerberos 5
|
||||||
Requires: openssl-libs >= 1:1.1.1d-4
|
Requires: openssl-libs >= 1:3.0.0
|
||||||
Requires: coreutils, gawk, grep, sed
|
Requires: coreutils, gawk, grep, sed
|
||||||
Requires: keyutils-libs >= 1.5.8
|
Requires: keyutils-libs >= 1.5.8
|
||||||
Requires: /etc/crypto-policies/back-ends/krb5.config
|
Requires: /etc/crypto-policies/back-ends/krb5.config
|
||||||
|
@ -635,6 +640,10 @@ exit 0
|
||||||
%{_libdir}/libkadm5srv_mit.so.*
|
%{_libdir}/libkadm5srv_mit.so.*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed May 19 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-4
|
||||||
|
- Port to OpenSSL 3 (alpha 15)
|
||||||
|
- Resolves: #1955873
|
||||||
|
|
||||||
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 1.19.1-3.1
|
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 1.19.1-3.1
|
||||||
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
|
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
From 7fb3126fd893eaf943734896c92355fe150b44d6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robbie Harwood <rharwood@redhat.com>
|
||||||
|
Date: Sat, 15 May 2021 18:04:58 -0400
|
||||||
|
Subject: [PATCH] softpkcs11: Remove all openssl deprecated functions
|
||||||
|
|
||||||
|
Rewrite add_pubkey_info() in terms of the EVP_PKEY interface. In this
|
||||||
|
process, fix its unchecked allocations and fail fast for non-RSA keys.
|
||||||
|
|
||||||
|
(cherry picked from commit ec4a325dc939da23967bb115bb5339963da80098)
|
||||||
|
---
|
||||||
|
src/configure.ac | 1 +
|
||||||
|
src/tests/softpkcs11/main.c | 83 +++++++++++++++++++++++--------------
|
||||||
|
2 files changed, 53 insertions(+), 31 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/configure.ac b/src/configure.ac
|
||||||
|
index 3e1052db7..eb6307468 100644
|
||||||
|
--- a/src/configure.ac
|
||||||
|
+++ b/src/configure.ac
|
||||||
|
@@ -1114,6 +1114,7 @@ int i = 1;
|
||||||
|
])], k5_cv_openssl_version_okay=yes, k5_cv_openssl_version_okay=no)])
|
||||||
|
old_LIBS="$LIBS"
|
||||||
|
AC_CHECK_LIB(crypto, PKCS7_get_signer_info)
|
||||||
|
+ AC_CHECK_FUNCS(EVP_PKEY_get_bn_param)
|
||||||
|
LIBS="$old_LIBS"
|
||||||
|
fi
|
||||||
|
if test "$k5_cv_openssl_version_okay" = yes && (test "$enable_pkinit" = yes || test "$enable_pkinit" = try); then
|
||||||
|
diff --git a/src/tests/softpkcs11/main.c b/src/tests/softpkcs11/main.c
|
||||||
|
index 500e3093d..c6f688dde 100644
|
||||||
|
--- a/src/tests/softpkcs11/main.c
|
||||||
|
+++ b/src/tests/softpkcs11/main.c
|
||||||
|
@@ -416,42 +416,63 @@ add_object_attribute(struct st_object *o,
|
||||||
|
static CK_RV
|
||||||
|
add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
|
||||||
|
{
|
||||||
|
- switch (key_type) {
|
||||||
|
- case CKK_RSA: {
|
||||||
|
- CK_BYTE *modulus = NULL;
|
||||||
|
- size_t modulus_len = 0;
|
||||||
|
- CK_ULONG modulus_bits = 0;
|
||||||
|
- CK_BYTE *exponent = NULL;
|
||||||
|
- size_t exponent_len = 0;
|
||||||
|
- const RSA *rsa;
|
||||||
|
- const BIGNUM *n, *e;
|
||||||
|
+ CK_BYTE *modulus = NULL, *exponent = 0;
|
||||||
|
+ size_t modulus_len = 0, exponent_len = 0;
|
||||||
|
+ CK_ULONG modulus_bits = 0;
|
||||||
|
+ CK_RV ret;
|
||||||
|
|
||||||
|
- rsa = EVP_PKEY_get0_RSA(key);
|
||||||
|
- RSA_get0_key(rsa, &n, &e, NULL);
|
||||||
|
- modulus_bits = BN_num_bits(n);
|
||||||
|
+#ifdef HAVE_EVP_PKEY_GET_BN_PARAM
|
||||||
|
+ BIGNUM *n = NULL, *e = NULL;
|
||||||
|
+#else
|
||||||
|
+ const RSA *rsa;
|
||||||
|
+ const BIGNUM *n, *e;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
- modulus_len = BN_num_bytes(n);
|
||||||
|
- modulus = malloc(modulus_len);
|
||||||
|
- BN_bn2bin(n, modulus);
|
||||||
|
+ if (key_type != CKK_RSA)
|
||||||
|
+ abort();
|
||||||
|
|
||||||
|
- exponent_len = BN_num_bytes(e);
|
||||||
|
- exponent = malloc(exponent_len);
|
||||||
|
- BN_bn2bin(e, exponent);
|
||||||
|
-
|
||||||
|
- add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
|
||||||
|
- add_object_attribute(o, 0, CKA_MODULUS_BITS,
|
||||||
|
- &modulus_bits, sizeof(modulus_bits));
|
||||||
|
- add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
|
||||||
|
- exponent, exponent_len);
|
||||||
|
-
|
||||||
|
- free(modulus);
|
||||||
|
- free(exponent);
|
||||||
|
+#ifdef HAVE_EVP_PKEY_GET_BN_PARAM
|
||||||
|
+ if (EVP_PKEY_get_bn_param(key, "n", &n) == 0 ||
|
||||||
|
+ EVP_PKEY_get_bn_param(key, "e", &e) == 0) {
|
||||||
|
+ ret = CKR_DEVICE_ERROR;
|
||||||
|
+ goto done;
|
||||||
|
}
|
||||||
|
- default:
|
||||||
|
- /* XXX */
|
||||||
|
- break;
|
||||||
|
+#else
|
||||||
|
+ rsa = EVP_PKEY_get0_RSA(key);
|
||||||
|
+ RSA_get0_key(rsa, &n, &e, NULL);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ modulus_bits = BN_num_bits(n);
|
||||||
|
+ modulus_len = BN_num_bytes(n);
|
||||||
|
+ exponent_len = BN_num_bytes(e);
|
||||||
|
+
|
||||||
|
+ modulus = malloc(modulus_len);
|
||||||
|
+ exponent = malloc(exponent_len);
|
||||||
|
+ if (modulus == NULL || exponent == NULL) {
|
||||||
|
+ ret = CKR_DEVICE_MEMORY;
|
||||||
|
+ goto done;
|
||||||
|
}
|
||||||
|
- return CKR_OK;
|
||||||
|
+
|
||||||
|
+ BN_bn2bin(n, modulus);
|
||||||
|
+ BN_bn2bin(e, exponent);
|
||||||
|
+
|
||||||
|
+ add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
|
||||||
|
+ add_object_attribute(o, 0, CKA_MODULUS_BITS,
|
||||||
|
+ &modulus_bits, sizeof(modulus_bits));
|
||||||
|
+ add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
|
||||||
|
+ exponent, exponent_len);
|
||||||
|
+
|
||||||
|
+ ret = CKR_OK;
|
||||||
|
+done:
|
||||||
|
+ free(modulus);
|
||||||
|
+ free(exponent);
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_EVP_PKEY_GET_BN_PARAM
|
||||||
|
+ BN_clear_free(n);
|
||||||
|
+ BN_clear_free(e);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue