| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-01-28 20:54:57 +08:00
										 |  |  |  * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <openssl/crypto.h>
 | 
					
						
							|  |  |  | #include <openssl/kdf.h>
 | 
					
						
							|  |  |  | #include <openssl/core_dispatch.h>
 | 
					
						
							|  |  |  | #include <openssl/core_names.h>
 | 
					
						
							|  |  |  | #include <openssl/params.h>
 | 
					
						
							|  |  |  | #include "prov/implementations.h"
 | 
					
						
							|  |  |  | #include "prov/provider_ctx.h"
 | 
					
						
							|  |  |  | #include "prov/kdfexchange.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-07 11:26:20 +08:00
										 |  |  | #include "prov/providercommon.h"
 | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  | static OSSL_FUNC_keyexch_newctx_fn kdf_tls1_prf_newctx; | 
					
						
							|  |  |  | static OSSL_FUNC_keyexch_newctx_fn kdf_hkdf_newctx; | 
					
						
							| 
									
										
										
										
											2020-07-31 22:05:57 +08:00
										 |  |  | static OSSL_FUNC_keyexch_newctx_fn kdf_scrypt_newctx; | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | static OSSL_FUNC_keyexch_init_fn kdf_init; | 
					
						
							|  |  |  | static OSSL_FUNC_keyexch_derive_fn kdf_derive; | 
					
						
							|  |  |  | static OSSL_FUNC_keyexch_freectx_fn kdf_freectx; | 
					
						
							|  |  |  | static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx; | 
					
						
							|  |  |  | static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params; | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  | static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params; | 
					
						
							|  |  |  | static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_hkdf_settable_ctx_params; | 
					
						
							| 
									
										
										
										
											2020-07-31 22:05:57 +08:00
										 |  |  | static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_scrypt_settable_ctx_params; | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     void *provctx; | 
					
						
							|  |  |  |     EVP_KDF_CTX *kdfctx; | 
					
						
							|  |  |  |     KDF_DATA *kdfdata; | 
					
						
							|  |  |  | } PROV_KDF_CTX; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 21:43:11 +08:00
										 |  |  | static void *kdf_newctx(const char *kdfname, void *provctx) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-07 11:26:20 +08:00
										 |  |  |     PROV_KDF_CTX *kdfctx; | 
					
						
							| 
									
										
										
										
											2020-08-04 21:43:11 +08:00
										 |  |  |     EVP_KDF *kdf = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 11:26:20 +08:00
										 |  |  |     if (!ossl_prov_is_running()) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX)); | 
					
						
							| 
									
										
										
										
											2020-08-04 21:43:11 +08:00
										 |  |  |     if (kdfctx == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kdfctx->provctx = provctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |     kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname, NULL); | 
					
						
							| 
									
										
										
										
											2020-08-04 21:43:11 +08:00
										 |  |  |     if (kdf == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     kdfctx->kdfctx = EVP_KDF_CTX_new(kdf); | 
					
						
							|  |  |  |     EVP_KDF_free(kdf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (kdfctx->kdfctx == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return kdfctx; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  |     OPENSSL_free(kdfctx); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  | #define KDF_NEWCTX(funcname, kdfname) \
 | 
					
						
							|  |  |  |     static void *kdf_##funcname##_newctx(void *provctx) \ | 
					
						
							|  |  |  |     { \ | 
					
						
							| 
									
										
										
										
											2020-08-04 21:43:11 +08:00
										 |  |  |         return kdf_newctx(kdfname, provctx); \ | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  | KDF_NEWCTX(tls1_prf, "TLS1-PRF") | 
					
						
							|  |  |  | KDF_NEWCTX(hkdf, "HKDF") | 
					
						
							| 
									
										
										
										
											2020-07-31 22:05:57 +08:00
										 |  |  | KDF_NEWCTX(scrypt, "SCRYPT") | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 20:00:53 +08:00
										 |  |  | static int kdf_init(void *vpkdfctx, void *vkdf, const OSSL_PARAM params[]) | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 11:26:20 +08:00
										 |  |  |     if (!ossl_prov_is_running() | 
					
						
							|  |  |  |             || pkdfctx == NULL | 
					
						
							|  |  |  |             || vkdf == NULL | 
					
						
							| 
									
										
										
										
											2021-02-25 07:08:54 +08:00
										 |  |  |             || !ossl_kdf_data_up_ref(vkdf)) | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     pkdfctx->kdfdata = vkdf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 20:00:53 +08:00
										 |  |  |     return kdf_set_ctx_params(pkdfctx, params); | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen, | 
					
						
							|  |  |  |                       size_t outlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 11:26:20 +08:00
										 |  |  |     if (!ossl_prov_is_running()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2021-01-14 22:53:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (secret == NULL) { | 
					
						
							|  |  |  |         *secretlen = EVP_KDF_CTX_get_kdf_size(pkdfctx->kdfctx); | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-26 08:09:27 +08:00
										 |  |  |     return EVP_KDF_derive(pkdfctx->kdfctx, secret, outlen, NULL); | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kdf_freectx(void *vpkdfctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     EVP_KDF_CTX_free(pkdfctx->kdfctx); | 
					
						
							| 
									
										
										
										
											2021-02-25 07:08:54 +08:00
										 |  |  |     ossl_kdf_data_free(pkdfctx->kdfdata); | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     OPENSSL_free(pkdfctx); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void *kdf_dupctx(void *vpkdfctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx; | 
					
						
							|  |  |  |     PROV_KDF_CTX *dstctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 11:26:20 +08:00
										 |  |  |     if (!ossl_prov_is_running()) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  |     dstctx = OPENSSL_zalloc(sizeof(*srcctx)); | 
					
						
							|  |  |  |     if (dstctx == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *dstctx = *srcctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  |     dstctx->kdfctx = EVP_KDF_CTX_dup(srcctx->kdfctx); | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  |     if (dstctx->kdfctx == NULL) { | 
					
						
							|  |  |  |         OPENSSL_free(dstctx); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-02-25 07:08:54 +08:00
										 |  |  |     if (!ossl_kdf_data_up_ref(dstctx->kdfdata)) { | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  |         EVP_KDF_CTX_free(dstctx->kdfctx); | 
					
						
							|  |  |  |         OPENSSL_free(dstctx); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return dstctx; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  |     return EVP_KDF_CTX_set_params(pkdfctx->kdfctx, params); | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-27 01:02:36 +08:00
										 |  |  | static const OSSL_PARAM *kdf_settable_ctx_params(ossl_unused void *vpkdfctx, | 
					
						
							|  |  |  |                                                  void *provctx, | 
					
						
							| 
									
										
										
										
											2020-08-04 21:43:11 +08:00
										 |  |  |                                                  const char *kdfname) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |     EVP_KDF *kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname, | 
					
						
							| 
									
										
										
										
											2020-08-04 21:43:11 +08:00
										 |  |  |                                  NULL); | 
					
						
							|  |  |  |     const OSSL_PARAM *params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (kdf == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     params = EVP_KDF_settable_ctx_params(kdf); | 
					
						
							|  |  |  |     EVP_KDF_free(kdf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return params; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  | #define KDF_SETTABLE_CTX_PARAMS(funcname, kdfname) \
 | 
					
						
							| 
									
										
										
										
											2021-02-27 01:02:36 +08:00
										 |  |  |     static const OSSL_PARAM *kdf_##funcname##_settable_ctx_params(void *vpkdfctx, \ | 
					
						
							|  |  |  |                                                                   void *provctx) \ | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  |     { \ | 
					
						
							| 
									
										
										
										
											2021-02-27 01:02:36 +08:00
										 |  |  |         return kdf_settable_ctx_params(vpkdfctx, provctx, kdfname); \ | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-03 23:18:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  | KDF_SETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF") | 
					
						
							|  |  |  | KDF_SETTABLE_CTX_PARAMS(hkdf, "HKDF") | 
					
						
							| 
									
										
										
										
											2020-07-31 22:05:57 +08:00
										 |  |  | KDF_SETTABLE_CTX_PARAMS(scrypt, "SCRYPT") | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define KDF_KEYEXCH_FUNCTIONS(funcname) \
 | 
					
						
							| 
									
										
										
										
											2020-09-28 10:28:29 +08:00
										 |  |  |     const OSSL_DISPATCH ossl_kdf_##funcname##_keyexch_functions[] = { \ | 
					
						
							| 
									
										
										
										
											2020-07-21 01:06:55 +08:00
										 |  |  |         { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_##funcname##_newctx }, \ | 
					
						
							|  |  |  |         { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init }, \ | 
					
						
							|  |  |  |         { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive }, \ | 
					
						
							|  |  |  |         { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx }, \ | 
					
						
							|  |  |  |         { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx }, \ | 
					
						
							|  |  |  |         { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params }, \ | 
					
						
							|  |  |  |         { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, \ | 
					
						
							|  |  |  |         (void (*)(void))kdf_##funcname##_settable_ctx_params }, \ | 
					
						
							|  |  |  |         { 0, NULL } \ | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | KDF_KEYEXCH_FUNCTIONS(tls1_prf) | 
					
						
							|  |  |  | KDF_KEYEXCH_FUNCTIONS(hkdf) | 
					
						
							| 
									
										
										
										
											2020-07-31 22:05:57 +08:00
										 |  |  | KDF_KEYEXCH_FUNCTIONS(scrypt) |