1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include <openssl/crypto.h> 16#include <openssl/ec.h> 17#include <openssl/ec_key.h> 18#include <openssl/err.h> 19#include <openssl/evp.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. 31struct 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. 46static struct fips_service_indicator_state *service_indicator_get(void) { 47 struct fips_service_indicator_state *indicator = 48 reinterpret_cast<fips_service_indicator_state *>(CRYPTO_get_thread_local( 49 OPENSSL_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE)); 50 51 if (indicator == NULL) { 52 indicator = reinterpret_cast<fips_service_indicator_state *>( 53 OPENSSL_malloc(sizeof(struct fips_service_indicator_state))); 54 if (indicator == NULL) { 55 return NULL; 56 } 57 58 indicator->lock_state = STATE_UNLOCKED; 59 indicator->counter = 0; 60 61 if (!CRYPTO_set_thread_local( 62 OPENSSL_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE, indicator, 63 OPENSSL_free)) { 64 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR); 65 return NULL; 66 } 67 } 68 69 return indicator; 70} 71 72static uint64_t service_indicator_get_counter(void) { 73 struct fips_service_indicator_state *indicator = service_indicator_get(); 74 if (indicator == NULL) { 75 return 0; 76 } 77 return indicator->counter; 78} 79 80uint64_t FIPS_service_indicator_before_call(void) { 81 return service_indicator_get_counter(); 82} 83 84uint64_t FIPS_service_indicator_after_call(void) { 85 return service_indicator_get_counter(); 86} 87 88void FIPS_service_indicator_update_state(void) { 89 struct fips_service_indicator_state *indicator = service_indicator_get(); 90 if (indicator && indicator->lock_state == STATE_UNLOCKED) { 91 indicator->counter++; 92 } 93} 94 95void FIPS_service_indicator_lock_state(void) { 96 struct fips_service_indicator_state *indicator = service_indicator_get(); 97 if (indicator == NULL) { 98 return; 99 } 100 101 // |FIPS_service_indicator_lock_state| and 102 // |FIPS_service_indicator_unlock_state| should not under/overflow in normal 103 // operation. They are still checked and errors added to facilitate testing in 104 // service_indicator_test.cc. This should only happen if lock/unlock are 105 // called in an incorrect order or multiple times in the same function. 106 const uint64_t new_state = indicator->lock_state + 1; 107 if (new_state < indicator->lock_state) { 108 // Overflow. This would imply that our call stack length has exceeded a 109 // |uint64_t| which impossible on a 64-bit system. 110 abort(); 111 } 112 113 indicator->lock_state = new_state; 114} 115 116void FIPS_service_indicator_unlock_state(void) { 117 struct fips_service_indicator_state *indicator = service_indicator_get(); 118 if (indicator == NULL) { 119 return; 120 } 121 122 if (indicator->lock_state == 0) { 123 abort(); 124 } 125 126 indicator->lock_state--; 127} 128 129void AEAD_GCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) { 130 const size_t key_len = EVP_AEAD_key_length(ctx->aead); 131 if (key_len == 16 || key_len == 32) { 132 FIPS_service_indicator_update_state(); 133 } 134} 135 136void AEAD_CCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) { 137 if (EVP_AEAD_key_length(ctx->aead) == 16 && ctx->tag_len == 4) { 138 FIPS_service_indicator_update_state(); 139 } 140} 141 142// is_ec_fips_approved returns one if the curve corresponding to the given NID 143// is FIPS approved, and zero otherwise. 144static int is_ec_fips_approved(int curve_nid) { 145 switch (curve_nid) { 146 case NID_secp224r1: 147 case NID_X9_62_prime256v1: 148 case NID_secp384r1: 149 case NID_secp521r1: 150 return 1; 151 default: 152 return 0; 153 } 154} 155 156// is_md_fips_approved_for_signing returns one if the given message digest type 157// is FIPS approved for signing, and zero otherwise. 158static int is_md_fips_approved_for_signing(int md_type) { 159 switch (md_type) { 160 case NID_sha224: 161 case NID_sha256: 162 case NID_sha384: 163 case NID_sha512: 164 case NID_sha512_256: 165 return 1; 166 default: 167 return 0; 168 } 169} 170 171// is_md_fips_approved_for_verifying returns one if the given message digest 172// type is FIPS approved for verifying, and zero otherwise. 173static int is_md_fips_approved_for_verifying(int md_type) { 174 switch (md_type) { 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 186static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx, 187 int (*md_ok)(int md_type)) { 188 if (EVP_MD_CTX_get0_md(ctx) == NULL) { 189 // Signature schemes without a prehash are currently never FIPS approved. 190 return; 191 } 192 193 EVP_PKEY_CTX *const pctx = ctx->pctx; 194 const EVP_PKEY *const pkey = EVP_PKEY_CTX_get0_pkey(pctx); 195 const int pkey_type = EVP_PKEY_id(pkey); 196 const int md_type = EVP_MD_CTX_type(ctx); 197 198 // EVP_PKEY_RSA_PSS SPKIs aren't supported. 199 if (pkey_type == EVP_PKEY_RSA) { 200 // Message digest used in the private key should be of the same type 201 // as the given one, so we extract the MD type from the |EVP_PKEY| 202 // and compare it with the type in |ctx|. 203 const EVP_MD *pctx_md; 204 if (!EVP_PKEY_CTX_get_signature_md(pctx, &pctx_md)) { 205 goto err; 206 } 207 if (EVP_MD_type(pctx_md) != md_type) { 208 goto err; 209 } 210 211 int padding; 212 if (!EVP_PKEY_CTX_get_rsa_padding(pctx, &padding)) { 213 goto err; 214 } 215 if (padding == RSA_PKCS1_PSS_PADDING) { 216 int salt_len; 217 const EVP_MD *mgf1_md; 218 if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pctx, &salt_len) || 219 !EVP_PKEY_CTX_get_rsa_mgf1_md(pctx, &mgf1_md) || 220 (salt_len != RSA_PSS_SALTLEN_DIGEST && 221 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.get()); 232 233 // Check if the MD type and the RSA key size are approved. 234 if (md_ok(md_type) && 235 (pkey_size == 256 || pkey_size == 384 || pkey_size == 512)) { 236 FIPS_service_indicator_update_state(); 237 } 238 } else if (pkey_type == EVP_PKEY_EC) { 239 // Check if the MD type and the elliptic curve are approved. 240 if (md_ok(md_type) && 241 is_ec_fips_approved(EC_GROUP_get_curve_name( 242 EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(ctx->pctx->pkey.get()))))) { 243 FIPS_service_indicator_update_state(); 244 } 245 } 246 247err: 248 // Ensure that junk errors aren't left on the queue. 249 ERR_clear_error(); 250} 251 252void EC_KEY_keygen_verify_service_indicator(const EC_KEY *eckey) { 253 if (is_ec_fips_approved(EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)))) { 254 FIPS_service_indicator_update_state(); 255 } 256} 257 258void 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 264void 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 281void EVP_DigestVerify_verify_service_indicator(const EVP_MD_CTX *ctx) { 282 return evp_md_ctx_verify_service_indicator(ctx, 283 is_md_fips_approved_for_verifying); 284} 285 286void EVP_DigestSign_verify_service_indicator(const EVP_MD_CTX *ctx) { 287 return evp_md_ctx_verify_service_indicator(ctx, 288 is_md_fips_approved_for_signing); 289} 290 291void HMAC_verify_service_indicator(const EVP_MD *evp_md) { 292 switch (EVP_MD_type(evp_md)) { 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 304void TLSKDF_verify_service_indicator(const EVP_MD *md) { 305 // HMAC-SHA{256, 384, 512} are approved for use in the KDF in TLS 1.2. These 306 // Key Derivation functions are to be used in the context of the TLS protocol. 307 switch (EVP_MD_type(md)) { 308 case NID_sha256: 309 case NID_sha384: 310 case NID_sha512: 311 FIPS_service_indicator_update_state(); 312 break; 313 } 314} 315 316#else 317 318uint64_t FIPS_service_indicator_before_call(void) { return 0; } 319 320uint64_t FIPS_service_indicator_after_call(void) { 321 // One is returned so that the return value is always greater than zero, the 322 // return value of |FIPS_service_indicator_before_call|. This makes everything 323 // report as "approved" in non-FIPS builds. 324 return 1; 325} 326 327#endif // BORINGSSL_FIPS 328