• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <openssl/crypto.h>
16 #include <openssl/ec.h>
17 #include <openssl/ec_key.h>
18 #include <openssl/evp.h>
19 #include <openssl/service_indicator.h>
20 
21 #include "../../evp/internal.h"
22 #include "../../internal.h"
23 #include "internal.h"
24 
25 #if defined(BORINGSSL_FIPS)
26 
27 #define STATE_UNLOCKED 0
28 
29 // fips_service_indicator_state is a thread-local structure that stores the
30 // state of the FIPS service indicator.
31 struct fips_service_indicator_state {
32   // lock_state records the number of times the indicator has been locked.
33   // When it is zero (i.e. |STATE_UNLOCKED|) then the indicator can be updated.
34   uint64_t lock_state;
35   // counter is the indicator state. It is incremented when an approved service
36   // completes.
37   uint64_t counter;
38 };
39 
40 // service_indicator_get returns a pointer to the |fips_service_indicator_state|
41 // for the current thread. It returns NULL on error.
42 //
43 // FIPS 140-3 requires that the module should provide the service indicator
44 // for approved services irrespective of whether the user queries it or not.
45 // Hence, it is lazily initialized in any call to an approved service.
service_indicator_get(void)46 static struct fips_service_indicator_state *service_indicator_get(void) {
47   struct fips_service_indicator_state *indicator = CRYPTO_get_thread_local(
48       OPENSSL_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE);
49 
50   if (indicator == NULL) {
51     indicator = OPENSSL_malloc(sizeof(struct fips_service_indicator_state));
52     if (indicator == NULL) {
53       OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE);
54       return NULL;
55     }
56 
57     indicator->lock_state = STATE_UNLOCKED;
58     indicator->counter = 0;
59 
60     if (!CRYPTO_set_thread_local(
61             OPENSSL_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE, indicator,
62             OPENSSL_free)) {
63       OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR);
64       return NULL;
65     }
66   }
67 
68   return indicator;
69 }
70 
service_indicator_get_counter(void)71 static uint64_t service_indicator_get_counter(void) {
72   struct fips_service_indicator_state *indicator = service_indicator_get();
73   if (indicator == NULL) {
74     return 0;
75   }
76   return indicator->counter;
77 }
78 
FIPS_service_indicator_before_call(void)79 uint64_t FIPS_service_indicator_before_call(void) {
80   return service_indicator_get_counter();
81 }
82 
FIPS_service_indicator_after_call(void)83 uint64_t FIPS_service_indicator_after_call(void) {
84   return service_indicator_get_counter();
85 }
86 
FIPS_service_indicator_update_state(void)87 void FIPS_service_indicator_update_state(void) {
88   struct fips_service_indicator_state *indicator = service_indicator_get();
89   if (indicator && indicator->lock_state == STATE_UNLOCKED) {
90     indicator->counter++;
91   }
92 }
93 
FIPS_service_indicator_lock_state(void)94 void FIPS_service_indicator_lock_state(void) {
95   struct fips_service_indicator_state *indicator = service_indicator_get();
96   if (indicator == NULL) {
97     return;
98   }
99 
100   // |FIPS_service_indicator_lock_state| and
101   // |FIPS_service_indicator_unlock_state| should not under/overflow in normal
102   // operation. They are still checked and errors added to facilitate testing in
103   // service_indicator_test.cc. This should only happen if lock/unlock are
104   // called in an incorrect order or multiple times in the same function.
105   const uint64_t new_state = indicator->lock_state + 1;
106   if (new_state < indicator->lock_state) {
107     // Overflow. This would imply that our call stack length has exceeded a
108     // |uint64_t| which impossible on a 64-bit system.
109     abort();
110   }
111 
112   indicator->lock_state = new_state;
113 }
114 
FIPS_service_indicator_unlock_state(void)115 void FIPS_service_indicator_unlock_state(void) {
116   struct fips_service_indicator_state *indicator = service_indicator_get();
117   if (indicator == NULL) {
118     return;
119   }
120 
121   if (indicator->lock_state == 0) {
122     abort();
123   }
124 
125   indicator->lock_state--;
126 }
127 
AEAD_GCM_verify_service_indicator(const EVP_AEAD_CTX * ctx)128 void AEAD_GCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) {
129   const size_t key_len = EVP_AEAD_key_length(ctx->aead);
130   if (key_len == 16 || key_len == 32) {
131     FIPS_service_indicator_update_state();
132   }
133 }
134 
AEAD_CCM_verify_service_indicator(const EVP_AEAD_CTX * ctx)135 void AEAD_CCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) {
136   if (EVP_AEAD_key_length(ctx->aead) == 16 && ctx->tag_len == 4) {
137     FIPS_service_indicator_update_state();
138   }
139 }
140 
141 // is_ec_fips_approved returns one if the curve corresponding to the given NID
142 // is FIPS approved, and zero otherwise.
is_ec_fips_approved(int curve_nid)143 static int is_ec_fips_approved(int curve_nid) {
144   switch (curve_nid) {
145     case NID_secp224r1:
146     case NID_X9_62_prime256v1:
147     case NID_secp384r1:
148     case NID_secp521r1:
149       return 1;
150     default:
151       return 0;
152   }
153 }
154 
155 // is_md_fips_approved_for_signing returns one if the given message digest type
156 // is FIPS approved for signing, and zero otherwise.
is_md_fips_approved_for_signing(int md_type)157 static int is_md_fips_approved_for_signing(int md_type) {
158   switch (md_type) {
159     case NID_sha224:
160     case NID_sha256:
161     case NID_sha384:
162     case NID_sha512:
163     case NID_sha512_256:
164       return 1;
165     default:
166       return 0;
167   }
168 }
169 
170 // is_md_fips_approved_for_verifying returns one if the given message digest
171 // type is FIPS approved for verifying, and zero otherwise.
is_md_fips_approved_for_verifying(int md_type)172 static int is_md_fips_approved_for_verifying(int md_type) {
173   switch (md_type) {
174     case NID_sha1:
175     case NID_sha224:
176     case NID_sha256:
177     case NID_sha384:
178     case NID_sha512:
179     case NID_sha512_256:
180       return 1;
181     default:
182       return 0;
183   }
184 }
185 
evp_md_ctx_verify_service_indicator(const EVP_MD_CTX * ctx,int rsa_1024_ok,int (* md_ok)(int md_type))186 static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx,
187                                                 int rsa_1024_ok,
188                                                 int (*md_ok)(int md_type)) {
189   if (EVP_MD_CTX_md(ctx) == NULL) {
190     // Signature schemes without a prehash are currently never FIPS approved.
191     goto err;
192   }
193 
194   EVP_PKEY_CTX *const pctx = ctx->pctx;
195   const EVP_PKEY *const pkey = EVP_PKEY_CTX_get0_pkey(pctx);
196   const int pkey_type = EVP_PKEY_id(pkey);
197   const int md_type = EVP_MD_CTX_type(ctx);
198 
199   // EVP_PKEY_RSA_PSS SPKIs aren't supported.
200   if (pkey_type == EVP_PKEY_RSA) {
201     // Message digest used in the private key should be of the same type
202     // as the given one, so we extract the MD type from the |EVP_PKEY|
203     // and compare it with the type in |ctx|.
204     const EVP_MD *pctx_md;
205     if (!EVP_PKEY_CTX_get_signature_md(pctx, &pctx_md)) {
206       goto err;
207     }
208     if (EVP_MD_type(pctx_md) != md_type) {
209       goto err;
210     }
211 
212     int padding;
213     if (!EVP_PKEY_CTX_get_rsa_padding(pctx, &padding)) {
214       goto err;
215     }
216     if (padding == RSA_PKCS1_PSS_PADDING) {
217       int salt_len;
218       const EVP_MD *mgf1_md;
219       if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pctx, &salt_len) ||
220           !EVP_PKEY_CTX_get_rsa_mgf1_md(pctx, &mgf1_md) ||
221           (salt_len != -1 && salt_len != (int)EVP_MD_size(pctx_md)) ||
222           EVP_MD_type(mgf1_md) != md_type) {
223         // Only PSS where saltLen == hashLen is tested with ACVP. Cases with
224         // non-standard padding functions are also excluded.
225         goto err;
226       }
227     }
228 
229     // The approved RSA key sizes for signing are 2048, 3072 and 4096 bits.
230     // Note: |EVP_PKEY_size| returns the size in bytes.
231     size_t pkey_size = EVP_PKEY_size(ctx->pctx->pkey);
232 
233     // Check if the MD type and the RSA key size are approved.
234     if (md_ok(md_type) &&
235         ((rsa_1024_ok && pkey_size == 128) || pkey_size == 256 ||
236          pkey_size == 384 || pkey_size == 512)) {
237       FIPS_service_indicator_update_state();
238     }
239   } else if (pkey_type == EVP_PKEY_EC) {
240     // Check if the MD type and the elliptic curve are approved.
241     if (md_ok(md_type) && is_ec_fips_approved(EC_GROUP_get_curve_name(
242                               ctx->pctx->pkey->pkey.ec->group))) {
243       FIPS_service_indicator_update_state();
244     }
245   }
246 
247  err:
248   // Ensure that junk errors aren't left on the queue.
249   ERR_clear_error();
250 }
251 
EC_KEY_keygen_verify_service_indicator(const EC_KEY * eckey)252 void EC_KEY_keygen_verify_service_indicator(const EC_KEY *eckey) {
253   if (is_ec_fips_approved(EC_GROUP_get_curve_name(eckey->group))) {
254     FIPS_service_indicator_update_state();
255   }
256 }
257 
ECDH_verify_service_indicator(const EC_KEY * ec_key)258 void ECDH_verify_service_indicator(const EC_KEY *ec_key) {
259   if (is_ec_fips_approved(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)))) {
260     FIPS_service_indicator_update_state();
261   }
262 }
263 
EVP_Cipher_verify_service_indicator(const EVP_CIPHER_CTX * ctx)264 void EVP_Cipher_verify_service_indicator(const EVP_CIPHER_CTX *ctx) {
265   switch (EVP_CIPHER_CTX_nid(ctx)) {
266     case NID_aes_128_ecb:
267     case NID_aes_192_ecb:
268     case NID_aes_256_ecb:
269 
270     case NID_aes_128_cbc:
271     case NID_aes_192_cbc:
272     case NID_aes_256_cbc:
273 
274     case NID_aes_128_ctr:
275     case NID_aes_192_ctr:
276     case NID_aes_256_ctr:
277       FIPS_service_indicator_update_state();
278   }
279 }
280 
EVP_DigestVerify_verify_service_indicator(const EVP_MD_CTX * ctx)281 void EVP_DigestVerify_verify_service_indicator(const EVP_MD_CTX *ctx) {
282   return evp_md_ctx_verify_service_indicator(ctx, /*rsa_1024_ok=*/1,
283                                              is_md_fips_approved_for_verifying);
284 }
285 
EVP_DigestSign_verify_service_indicator(const EVP_MD_CTX * ctx)286 void EVP_DigestSign_verify_service_indicator(const EVP_MD_CTX *ctx) {
287   return evp_md_ctx_verify_service_indicator(ctx, /*rsa_1024_ok=*/0,
288                                              is_md_fips_approved_for_signing);
289 }
290 
HMAC_verify_service_indicator(const EVP_MD * evp_md)291 void HMAC_verify_service_indicator(const EVP_MD *evp_md) {
292   switch (evp_md->type) {
293     case NID_sha1:
294     case NID_sha224:
295     case NID_sha256:
296     case NID_sha384:
297     case NID_sha512:
298     case NID_sha512_256:
299       FIPS_service_indicator_update_state();
300       break;
301   }
302 }
303 
TLSKDF_verify_service_indicator(const EVP_MD * md)304 void TLSKDF_verify_service_indicator(const EVP_MD *md) {
305   // HMAC-MD5, HMAC-SHA1, and HMAC-MD5/HMAC-SHA1 (both used concurrently) are
306   // approved for use in the KDF in TLS 1.0/1.1.
307   // HMAC-SHA{256, 384, 512} are approved for use in the KDF in TLS 1.2.
308   // These Key Derivation functions are to be used in the context of the TLS
309   // protocol.
310   switch (EVP_MD_type(md)) {
311     case NID_md5:
312     case NID_sha1:
313     case NID_md5_sha1:
314     case NID_sha256:
315     case NID_sha384:
316     case NID_sha512:
317       FIPS_service_indicator_update_state();
318       break;
319   }
320 }
321 
322 #else
323 
FIPS_service_indicator_before_call(void)324 uint64_t FIPS_service_indicator_before_call(void) { return 0; }
325 
FIPS_service_indicator_after_call(void)326 uint64_t FIPS_service_indicator_after_call(void) {
327   // One is returned so that the return value is always greater than zero, the
328   // return value of |FIPS_service_indicator_before_call|. This makes everything
329   // report as "approved" in non-FIPS builds.
330   return 1;
331 }
332 
333 #endif  // BORINGSSL_FIPS
334