diff options
Diffstat (limited to 'board/cr50/dcrypto/fips.c')
-rw-r--r-- | board/cr50/dcrypto/fips.c | 219 |
1 files changed, 147 insertions, 72 deletions
diff --git a/board/cr50/dcrypto/fips.c b/board/cr50/dcrypto/fips.c index 349117d49b..f08b54aea7 100644 --- a/board/cr50/dcrypto/fips.c +++ b/board/cr50/dcrypto/fips.c @@ -145,6 +145,8 @@ static bool fips_sha256_kat(void) static const uint8_t in[] = /* "etaonrishd" */ { 0x65, 0x74, 0x61, 0x6f, 0x6e, 0x72, 0x69, 0x73, 0x68, 0x64 }; + uint8_t in_mem[sizeof(in)]; + static const uint8_t ans[] = { 0xf5, 0x53, 0xcd, 0xb8, 0xcf, 0x1, 0xee, 0x17, 0x9b, 0x93, 0xc9, 0x68, 0xc0, 0xea, 0x40, 0x91, 0x6, 0xec, 0x8e, 0x11, 0x96, @@ -152,10 +154,13 @@ static bool fips_sha256_kat(void) 0x50, 0x4f, 0x47, 0x57 }; SHA256_hw_init(&ctx); - SHA256_update(&ctx, in, sizeof(in)); - return !(fips_break_cmd == FIPS_BREAK_SHA256) && - (DCRYPTO_equals(SHA256_final(&ctx), ans, SHA256_DIGEST_SIZE) == - DCRYPTO_OK); + memcpy(in_mem, in, sizeof(in)); + if (fips_break_cmd == FIPS_BREAK_SHA256) + in_mem[0] ^= 1; + + SHA256_update(&ctx, in_mem, sizeof(in_mem)); + return DCRYPTO_equals(SHA256_final(&ctx), ans, SHA256_DIGEST_SIZE) == + DCRYPTO_OK; } /* KAT for HMAC-SHA256, test values from OpenSSL. */ @@ -172,6 +177,8 @@ static bool fips_hmac_sha256_kat(void) static const uint8_t in[] = /* "Sample text" */ { 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x74, 0x65, 0x78, 0x74 }; + uint8_t in_mem[sizeof(in)]; + static const uint8_t ans[] = { 0xe9, 0x17, 0xc1, 0x7b, 0x4c, 0x6b, 0x77, 0xda, 0xd2, 0x30, 0x36, 0x02, 0xf5, 0x72, 0x33, 0x87, 0x9f, 0xc6, 0x6e, 0x7b, 0x7e, @@ -179,10 +186,12 @@ static bool fips_hmac_sha256_kat(void) 0xff, 0xda, 0x24, 0xf4 }; HMAC_SHA256_hw_init(&ctx, k, sizeof(k)); - HMAC_SHA256_update(&ctx, in, sizeof(in)); - return !(fips_break_cmd == FIPS_BREAK_HMAC_SHA256) && - (DCRYPTO_equals(HMAC_SHA256_hw_final(&ctx), ans, - SHA256_DIGEST_SIZE) == DCRYPTO_OK); + memcpy(in_mem, in, sizeof(in)); + if (fips_break_cmd == FIPS_BREAK_SHA256) + in_mem[0] ^= 1; + HMAC_SHA256_update(&ctx, in_mem, sizeof(in_mem)); + return DCRYPTO_equals(HMAC_SHA256_hw_final(&ctx), ans, + SHA256_DIGEST_SIZE) == DCRYPTO_OK; } /** @@ -325,23 +334,26 @@ static bool fips_hmac_drbg_generate_kat(struct drbg_ctx *ctx) 0xf1, 0x32, 0xf6, 0x86, 0xb7, 0x60, 0xf0, 0x12 }; uint8_t buf[128]; + int passed; + + passed = hmac_drbg_generate(ctx, buf, sizeof(buf), NULL, 0) - + HMAC_DRBG_SUCCESS; - hmac_drbg_generate(ctx, buf, sizeof(buf), NULL, 0); /* Verify internal drbg state */ - if (DCRYPTO_equals(ctx->v, V2, sizeof(V2)) != DCRYPTO_OK || - DCRYPTO_equals(ctx->k, K2, sizeof(K2)) != DCRYPTO_OK) { - return false; - } + passed |= DCRYPTO_equals(ctx->v, V2, sizeof(V2)) - DCRYPTO_OK; + passed |= DCRYPTO_equals(ctx->k, K2, sizeof(K2)) - DCRYPTO_OK; - hmac_drbg_reseed(ctx, drbg_entropy2, sizeof(drbg_entropy2), - drbg_addtl_input2, sizeof(drbg_addtl_input2), NULL, 0); - /** - * reuse entropy buffer to avoid allocating too much stack and memory - * it will be cleaned up in TRNG health test - */ - hmac_drbg_generate(ctx, buf, sizeof(buf), NULL, 0); - return !(fips_break_cmd == FIPS_BREAK_HMAC_DRBG) && - DCRYPTO_equals(buf, KA, sizeof(KA) == DCRYPTO_OK); + memcpy(buf, drbg_entropy2, sizeof(drbg_entropy2)); + if (fips_break_cmd == FIPS_BREAK_HMAC_DRBG) + buf[0] ^= 1; + + hmac_drbg_reseed(ctx, buf, sizeof(drbg_entropy2), drbg_addtl_input2, + sizeof(drbg_addtl_input2), NULL, 0); + + passed |= hmac_drbg_generate(ctx, buf, sizeof(buf), NULL, 0) - + HMAC_DRBG_SUCCESS; + passed |= DCRYPTO_equals(buf, KA, sizeof(KA)) - DCRYPTO_OK; + return passed == 0; } /* Known-answer test for HMAC_DRBG SHA256. */ @@ -354,58 +366,113 @@ static bool fips_hmac_drbg_kat(void) fips_hmac_drbg_generate_kat(&ctx); } -/* Known-answer test for ECDSA NIST P-256 verify. */ -static bool fips_ecdsa_verify_kat(void) +#ifdef CONFIG_FIPS_ECDSA_PWCT +static bool fips_ecdsa_sign_pwct(void) { - static const p256_int qx = { .a = { 0xf49abf3c, 0xf82e6e12, 0x7a67c074, - 0x5134e16f, 0xf8957a0c, 0xef4344a7, - 0xd4bb3cb7, 0xe424dc61 } }; - static const p256_int qy = { .a = { 0xdfaee927, 0x3d6f60e7, 0xac85d124, - 0x127e5965, 0xe1dddaf0, 0x1545949d, - 0xa2bc4865, 0x970eed7a } }; - static const p256_int r = { .a = { 0xd9347f4f, 0xb72f981f, 0x6349b9da, - 0x2ff540c7, 0x42017c64, 0x910be331, - 0xa49c705c, 0xbf96b99a } }; - static const p256_int s = { .a = { 0x57ec871c, 0x920b9e0f, 0x75d98f31, - 0x444e3230, 0x15abdf12, 0xe03b9cd4, - 0x819089c2, 0x17c55095 } }; - static const uint8_t msg[128] = { - 0xe1, 0x13, 0x0a, 0xf6, 0xa3, 0x8c, 0xcb, 0x41, 0x2a, 0x9c, - 0x8d, 0x13, 0xe1, 0x5d, 0xbf, 0xc9, 0xe6, 0x9a, 0x16, 0x38, - 0x5a, 0xf3, 0xc3, 0xf1, 0xe5, 0xda, 0x95, 0x4f, 0xd5, 0xe7, - 0xc4, 0x5f, 0xd7, 0x5e, 0x2b, 0x8c, 0x36, 0x69, 0x92, 0x28, - 0xe9, 0x28, 0x40, 0xc0, 0x56, 0x2f, 0xbf, 0x37, 0x72, 0xf0, - 0x7e, 0x17, 0xf1, 0xad, 0xd5, 0x65, 0x88, 0xdd, 0x45, 0xf7, - 0x45, 0x0e, 0x12, 0x17, 0xad, 0x23, 0x99, 0x22, 0xdd, 0x9c, - 0x32, 0x69, 0x5d, 0xc7, 0x1f, 0xf2, 0x42, 0x4c, 0xa0, 0xde, - 0xc1, 0x32, 0x1a, 0xa4, 0x70, 0x64, 0xa0, 0x44, 0xb7, 0xfe, - 0x3c, 0x2b, 0x97, 0xd0, 0x3c, 0xe4, 0x70, 0xa5, 0x92, 0x30, - 0x4c, 0x5e, 0xf2, 0x1e, 0xed, 0x9f, 0x93, 0xda, 0x56, 0xbb, - 0x23, 0x2d, 0x1e, 0xeb, 0x00, 0x35, 0xf9, 0xbf, 0x0d, 0xfa, - 0xfd, 0xcc, 0x46, 0x06, 0x27, 0x2b, 0x20, 0xa3 - }; + /** + * Use fixed key pair: + * d = 1 + * x = 6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296 + * y = 4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5 + */ + p256_int d; + static const p256_int x = { .a = { 0xD898C296, 0xF4A13945, 0x2DEB33A0, + 0x77037D81, 0x63A440F2, 0xF8BCE6E5, + 0xE12C4247, 0x6B17D1F2 } }; - p256_int p256_digest; - struct sha256_digest digest; - uint8_t bad_msg[128]; + static const p256_int y = { .a = { 0x37BF51F5, 0xCBB64068, 0x6B315ECE, + 0x2BCE3357, 0x7C0F9E16, 0x8EE7EB4A, + 0xFE1A7F9B, 0x4FE342E2 } }; + + memset(&d, 0, sizeof(d)); + d.a[0] = 1; /* d = 1 in little-endian */ + + /** + * Note, fips_drbg is not instantiated yet, but rather is in + * pre-determined state with K=[0], V=[0]. + */ + return DCRYPTO_p256_key_pwct(&fips_drbg, &d, &x, &y); +} +#endif + +/** + * Test vector from https://csrc.nist.gov/CSRC/media/Projects/ + * Cryptographic-Algorithm-Validation-Program/ + * documents/dss/186-4ecdsatestvectors.zip + * P-256, SHA2-256, case 1 + * + * Msg = 5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf41 + * 6983fe165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5473e + * 253605fb1ddfd28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17cc934a9 + * d791e91491eb3754d03799790fe2d308d16146d5c9b0d0debd97d79ce8 + * digest = 0x44, 0xac, 0xf6, 0xb7, 0xe3, 0x6c, 0x13, 0x42, 0xc2, 0xc5, 0x89, + * 0x72, 0x04, 0xfe, 0x09, 0x50, 0x4e, 0x1e, 0x2e, 0xfb, 0x1a, 0x90, + * 0x03, 0x77, 0xdb, 0xc4, 0xe7, 0xa6, 0xa1, 0x33, 0xec, 0x56 + * d = 519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464 + * Qx = 1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83 + * Qy = ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9 + * k = 94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de + * R = f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac + * S = 8bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903 + * + * All values are stored in internal little-endian representation. + * + */ +static bool fips_ecdsa_sign_verify_kat(void) +{ + static const uint8_t msg_digest[32] = { + 0x44, 0xac, 0xf6, 0xb7, 0xe3, 0x6c, 0x13, 0x42, + 0xc2, 0xc5, 0x89, 0x72, 0x04, 0xfe, 0x09, 0x50, + 0x4e, 0x1e, 0x2e, 0xfb, 0x1a, 0x90, 0x03, 0x77, + 0xdb, 0xc4, 0xe7, 0xa6, 0xa1, 0x33, 0xec, 0x56 + }; + static const p256_int d = { .a = { 0xda72b464, 0xca54a56d, 0x0b4e3eac, + 0x5b44c813, 0x59f4771a, 0x1f4fa8ee, + 0x715f8b58, 0x519b423d } }; + + static const p256_int k = { .a = { 0x642a68de, 0xb9670787, 0x824f5d33, + 0x3b4a6247, 0xf9e93c7f, 0xa280f245, + 0x4b906a61, 0x94a1bbb1 } }; + + static const p256_int Qx = { .a = { 0xc271bf83, 0x3c59ff46, 0x4bbfb12f, + 0xd3565de9, 0x48db8fcc, 0xf033bfa2, + 0x075fc7f4, 0x1ccbe91c } }; + static const p256_int Qy = { .a = { 0xa89a4ca9, 0xdc7ccd5c, 0xb7404e78, + 0x6db7ca93, 0x0e6113e0, 0x1a1fdb2c, + 0x8811f9a2, 0xce4014c6 } }; + static const p256_int R = { .a = { 0x79c8c2ac, 0xcabb5e6f, 0x6a555a7a, + 0x2afd6b1f, 0x629527ed, 0x8843e3d6, + 0xb514795b, 0xf3ac8061 } }; + + static const p256_int S = { .a = { 0xcc058903, 0x3ccdda2a, 0xe96f175a, + 0xef97b218, 0x2bf7371c, 0x786c7626, + 0xca05a6b2, 0x8bf77819 } }; + + p256_int msg, r, s; int passed; - SHA256_hw_hash(msg, sizeof(msg), &digest); - p256_from_bin(digest.b8, &p256_digest); - passed = dcrypto_p256_ecdsa_verify(&qx, &qy, &p256_digest, &r, &s); - if (!passed) - return false; + p256_from_bin(msg_digest, &msg); + + /* KAT for ECDSA signing with fixed k. */ + passed = dcrypto_p256_ecdsa_sign_raw(&k, &d, &msg, &r, &s) - 1; + + passed |= DCRYPTO_equals(r.a, R.a, sizeof(R)) - DCRYPTO_OK; + passed |= DCRYPTO_equals(s.a, S.a, sizeof(S)) - DCRYPTO_OK; + + if (fips_break_cmd == FIPS_BREAK_ECDSA) + msg.a[0] ^= 1; + + /* KAT for verification */ + passed |= dcrypto_p256_ecdsa_verify(&Qx, &Qy, &msg, &r, &s) - 1; + /** - * create bad_msg same as msg but has one bit flipped in byte 92 (0x0a - * vs 0x1a) this is to save space in flash vs. having bad message as - * constant + * Flip 1 bit in digest. Signature verification should fail. */ - memcpy(bad_msg, msg, sizeof(msg)); - bad_msg[92] ^= 0x10; - SHA256_hw_hash(bad_msg, sizeof(bad_msg), &digest); - p256_from_bin(digest.b8, &p256_digest); - passed = dcrypto_p256_ecdsa_verify(&qx, &qy, &p256_digest, &r, &s); - return !(fips_break_cmd == FIPS_BREAK_ECDSA) && (passed == 0); + msg.a[5] ^= 0x10; + + passed |= dcrypto_p256_ecdsa_verify(&Qx, &Qy, &msg, &r, &s); + + return passed == 0; } #ifdef CONFIG_FIPS_AES_CBC_256 @@ -607,6 +674,10 @@ void fips_power_up_tests(void) starttime = fips_vtable->get_time().val; + /* SHA2-256 is used for self-integrity test, so check it first. */ + if (!fips_sha256_kat()) + _fips_status |= FIPS_FATAL_SHA256; + if (fips_self_integrity() != DCRYPTO_OK) _fips_status |= FIPS_FATAL_SELF_INTEGRITY; @@ -621,8 +692,6 @@ void fips_power_up_tests(void) if (EC_SUCCESS == fips_vtable->shared_mem_acquire(FIPS_KAT_STACK_SIZE, &stack_buf)) { stack = stack_buf + FIPS_KAT_STACK_SIZE; - if (!call_on_stack(stack, &fips_sha256_kat)) - _fips_status |= FIPS_FATAL_SHA256; if (!call_on_stack(stack, &fips_hmac_sha256_kat)) _fips_status |= FIPS_FATAL_HMAC_SHA256; /** @@ -632,12 +701,18 @@ void fips_power_up_tests(void) * first call to TRNG warm-up */ fips_trng_startup(0); - if (!call_on_stack(stack, &fips_ecdsa_verify_kat)) - _fips_status |= FIPS_FATAL_ECDSA; if (!call_on_stack(stack, &fips_hmac_drbg_kat)) _fips_status |= FIPS_FATAL_HMAC_DRBG; +#ifdef CONFIG_FIPS_ECDSA_PWCT + if (!call_on_stack(stack, &fips_ecdsa_sign_pwct)) + _fips_status |= FIPS_FATAL_ECDSA; +#endif + + if (!call_on_stack(stack, &fips_ecdsa_sign_verify_kat)) + _fips_status |= FIPS_FATAL_ECDSA; + #ifdef CONFIG_FIPS_AES_CBC_256 if (!call_on_stack(stack, &fips_aes256_kat)) _fips_status |= FIPS_FATAL_AES256; |