1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/*
* Copyright 2023 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file sa_provider.h
*
* sa_provider implements an OpenSSL 3 Provider that delegates its implementation to SecApi 3. Users can use the OpenSSL
* API, but SecApi 3 will be used to perform the cryptographic processing.
*
* To use a provider, users must call sa_get_provider(). This will create an OpenSSL Library Context and initialize it
* with a base provider and the SecApi 3 provider. The OpenSSL Library Context must not be freed.
*
* Private keys that have been imported into SecApi 3 should be loaded into OpenSSL using the EVP_PKEY_fromdata
* function using the OSSL_PARAM_SA_KEY parameter. Including the OSSL_PARAM_SA_KEY_DELETE parameter causes EVP_PKEY
* object to take ownership of the key and sa_key_release will be called when the EVP_PKEY object is freed:
*
* Example:
* --------
* ```
* sa_key key = // Load key into SecApi 3;
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* OSSL_PARAM params[] = {
* OSSL_PARAM_construct_uint64(OSSL_PARAM_SA_KEY, key),
* OSSL_PARAM_construct_int(OSSL_PARAM_SA_KEY_DELETE, 1),
* OSSL_PARAM_construct_end()};
* EVP_PKEY_CTX* = EVP_PKEY_CTX_new_from_name(lib_ctx, "RSA", nullptr);
* EVP_PKEY_fromdata_init(evp_pkey_ctx);
* EVP_PKEY* evp_pkey = NULL;
* EVP_PKEY_fromdata(evp_pkey_ctx, &evp_pkey, EVP_PKEY_KEYPAIR, params);
* ```
*
* A Clear PKCS8 formatted private key can also be read into an EVP_PKEY.
* Example:
* --------
* ```
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* uint8_t* clear_pkcs8_key = // Retrieve PKCS8 formatted key bytes.
* size_t clear_pkcs8_key_length = // Retrieve PKCS8 formatted key size.
* const uint8_t* p_clear_pkcs8_key = clear_pkcs8_key;
* EVP_PKEY* evp_pkey = d2i_AutoPrivateKey_ex(NULL, &p_clear_pkcs8_key, clear_pkcs8_key_length, lib_ctx, NULL);
* ```
*
* Examples of SecApi 3 Usage with OpenSSL:
* ========================================
* These examples assume the private key has been imported using the above examples.
*
* Signing (RSA, EC, ED25519, ED448)
* ---------------------------------
* ```
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* EVP_MD_CTX* evp_md_ctx = EVP_MD_CTX_new();
* EVP_PKEY_CTX* evp_pkey_ctx;
* // Padding parameters can alternatively be passed into params parameter.
* EVP_DigestSignInit_ex(evp_md_ctx, &evp_pkey_ctx, "SHA256", lib_ctx, NULL, evp_pkey, NULL);
* EVP_PKEY_CTX_set_rsa_padding(evp_pkey_ctx, RSA_PKCS1_PSS_PADDING);
* EVP_PKEY_CTX_set_rsa_pss_saltlen(evp_pkey_ctx, 16);
* EVP_DigestSignUpdate(evp_md_ctx, data, data_length);
* EVP_DigestSignFinal(evp_md_ctx, signature, &signature_length);
* EVP_MD_CTX_free(evp_md_ctx);
* ```
*
* Signing Predigested Content (RSA, EC)
* -------------------------------------
* ```
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* EVP_PKEY_CTX* evp_pkey_ctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, evp_pkey, nullptr);
* // Padding parameters can alternatively be passed into params parameter.
* EVP_PKEY_sign_init_ex(evp_pkey_ctx, NULL);
* EVP_PKEY_CTX_set_rsa_padding(evp_pkey_ctx, RSA_PKCS1_PSS_PADDING);
* EVP_PKEY_CTX_set_rsa_pss_saltlen(evp_pkey_ctx, 16);
* EVP_PKEY_CTX_set_signature_md(evp_pkey_ctx, evp_md);
* EVP_PKEY_sign(evp_pkey_ctx, signature, &signature_length, digest, digest_length);
* EVP_MD_CTX_free(evp_md_ctx);
* EVP_PKEY_CTX_free(evp_pkey_ctx);
* ```
*
* Decryption (RSA)
* ----------------
* ```
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* EVP_PKEY_CTX* evp_pkey_ctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, evp_pkey, nullptr);
* // Padding parameters can alternatively be passed into params parameter.
* EVP_PKEY_decrypt_init_ex(evp_pkey_ctx, NULL);
* EVP_PKEY_CTX_set_rsa_padding(evp_pkey_ctx, RSA_PKCS1_PADDING);
* EVP_PKEY_decrypt(evp_pkey_ctx, decrypted_data, &decrypted_data_length, encrypted_data, encrypted_data_length);
* EVP_PKEY_CTX_free(evp_pkey_ctx);
* ```
*
* Derivation (DH, EC, X25519, X448)
* ---------------------------------
* ```
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* EVP_PKEY_CTX* evp_pkey_ctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, evp_pkey, nullptr);
* EVP_PKEY_derive_init(evp_pkey_ctx);
* EVP_PKEY_derive_set_peer(evp_pkey_ctx, other_public_key);
* EVP_PKEY_derive(evp_pkey_ctx, shared_secret, &shared_secret_length);
* sa_key shared_secret_key = *((sa_key*)shared_secret);
* EVP_PKEY_CTX_free(evp_pkey_ctx);
* EVP_PKEY_free(evp_pkey);
* ```
*
* KDF (HMAC, CONCAT a.k.a. SSKDF, ANSI_X963 a.k.a. X963KDF, CMAC a.k.a. KBKDF)
* ----------------------------------------------------------------------------
* ```
* sa_key shared_secret_key = // shared secret key potentially derived through DH, EC, X25519, or X448
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* EVP_KDF* evp_kdf = EVP_KDF_fetch(lib_ctx, "HMAC", NULL);
* EVP_KDF_CTX* evp_kdf_ctx = EVP_KDF_CTX_new(evp_kdf);
* OSSL_PARAM params[] = {
* OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, shared_secret_key, sizeof(sa_key)),
* OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, "SHA256", 6),
* OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, salt, salt_length),
* OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, info, info_length),
* OSSL_PARAM_END};
* EVP_KDF_derive(evp_kdf_ctx, derived, derived_length, params);
* sa_key derived_key = *((sa_key*)derived);
* EVP_KDF_CTX_free(evp_kdf_ctx);
* EVP_KDF_free(evp_kdf);
* ```
*
* MAC (HMAC, CMAC)
* ----------------
* ```
* sa_key key = // Load key into SecApi 3;
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* EVP_MAC* evp_mac = EVP_MAC_fetch(lib_ctx, "HMAC", NULL);
* OSSL_PARAM params[] = {
* OSSL_PARAM_construct_uint64(OSSL_PARAM_SA_KEY, key),
* OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, "SHA256", 6),
* OSSL_PARAM_construct_end()};
* // A clear raw HMAC/CMAC key can alternatively be passed into the key parameter--SA_KEY_DELETE will automatically
* // be set to true.
* EVP_MAC* evp_mac = EVP_MAC_init(evp_mac_ctx.get(), NULL, 0, params);
* EVP_MAC_update(evp_mac_ctx, data, data_length);
* size_t mac_out_length;
* EVP_MAC_final(evp_mac_ctx, mac, &mac_out_length, mac_length);
* EVP_MAC_free(evp_mac_ctx);
* ```
*
* Encryption/Decryption (AES, CHACHA20)
* -------------------------------------
* ```
* sa_key key = // Load key into SecApi 3;
* OSSL_LIB_CTX* lib_ctx = sa_get_provider();
* EVP_CIPHER* evp_cipher = EVP_CIPHER_fetch(lib_ctx, "aes-128-cbc", nullptr);
* OSSL_PARAM params[] = {
* OSSL_PARAM_construct_uint64(OSSL_PARAM_SA_KEY, key),
* OSSL_PARAM_construct_end()};
* EVP_CIPHER_CTX* evp_cipher_ctx = EVP_CIPHER_CTX_new();
* // A clear raw symmetric key can alternatively be passed into the key parameter--SA_KEY_DELETE will automatically
* // be set to true.
* EVP_CipherInit_ex2(evp_cipher_ctx, evp_cipher, NULL, iv, 1, params); // 1 = enc, 0 = dec
* EVP_CipherUpdate(evp_cipher_ctx, encrypted_data, &length, data, data_length);
* EVP_CipherFinal(evp_cipher_ctx, encrypted_data + total_length, &length);
* EVP_CIPHER_CTX_free(evp_cipher_ctx);
* EVP_CIPHER_free(cipher);
* ```
*/
extern "C" OPENSSL_VERSION_NUMBER >= 0x30000000
/**
* The provider ID used to register the SecApi 3 provider.
*/
/**
* The name of the SecApi 3 provider.
*/
/**
* The OSSL_PARAM_SA_KEY parameter is used to import the SecApi 3 key handle into an EVP_PKEY object, for private keys,
* or, for symmetric keys, into the the EVP_CIPHER_CTX object when used with EVP_CipherInit_ex2 or into the EVP_MAC_CTX
* object when used with EVP_MAC_init.
*/
/**
* The OSSL_PARAM_SA_KEY_DELETE parameter, when set to 1, directs the SecApi 3 provider to release the sa_key handle
* when the EVP_PKEY, EVP_MAC_CTX, or EVP_CIPHER_CTX object is freed (the EVP_PKEY, EVP_MAC_CTX, or EVP_CIPHER_CTX
* object assumes control of the handle). If the parameter is 0 or not set, the SecApi 3 provider assumes that the
* caller will release the sa_key handle when they are done using it.
*/
/**
* Retrieves the OpenSSL library context initialized with the SecApi3 provider.
*
* @return NULL if not successful.
*/
OSSL_LIB_CTX* ;
}
//SA_PROVIDER_H