]>
Commit | Line | Data |
---|---|---|
7bb82f92 SL |
1 | /* |
2 | * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <string.h> | |
11 | #include <openssl/evp.h> | |
12 | #include <openssl/params.h> | |
13 | #include "selftest.h" | |
14 | ||
15 | #define FIPS_STATE_INIT 0 | |
16 | #define FIPS_STATE_RUNNING 1 | |
17 | #define FIPS_STATE_SELFTEST 2 | |
18 | #define FIPS_STATE_ERROR 3 | |
19 | ||
20 | /* The size of a temp buffer used to read in data */ | |
21 | #define INTEGRITY_BUF_SIZE (4096) | |
22 | #define MAX_MD_SIZE 64 | |
23 | #define MAC_NAME "HMAC" | |
24 | #define DIGEST_NAME "SHA256" | |
25 | ||
26 | static int FIPS_state = FIPS_STATE_INIT; | |
27 | static unsigned char fixed_key[32] = { 0 }; | |
28 | ||
29 | /* | |
30 | * Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify | |
31 | * the result matches the expected value. | |
32 | * Return 1 if verified, or 0 if it fails. | |
33 | */ | |
34 | static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb, | |
35 | unsigned char *expected, size_t expected_len, | |
36 | OPENSSL_CTX *libctx) | |
37 | { | |
38 | int ret = 0, status; | |
39 | unsigned char out[MAX_MD_SIZE]; | |
40 | unsigned char buf[INTEGRITY_BUF_SIZE]; | |
41 | size_t bytes_read = 0, out_len = 0; | |
42 | EVP_MAC *mac = NULL; | |
43 | EVP_MAC_CTX *ctx = NULL; | |
44 | OSSL_PARAM params[3], *p = params; | |
45 | ||
46 | mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL); | |
47 | ctx = EVP_MAC_CTX_new(mac); | |
48 | if (mac == NULL || ctx == NULL) | |
49 | goto err; | |
50 | ||
51 | *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, | |
52 | strlen(DIGEST_NAME) + 1); | |
53 | *p++ = OSSL_PARAM_construct_octet_string("key", fixed_key, | |
54 | sizeof(fixed_key)); | |
55 | *p = OSSL_PARAM_construct_end(); | |
56 | ||
57 | if (EVP_MAC_CTX_set_params(ctx, params) <= 0 | |
58 | || !EVP_MAC_init(ctx)) | |
59 | goto err; | |
60 | ||
61 | while (1) { | |
62 | status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read); | |
63 | if (status != 1) | |
64 | break; | |
65 | if (!EVP_MAC_update(ctx, buf, bytes_read)) | |
66 | goto err; | |
67 | } | |
68 | if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out))) | |
69 | goto err; | |
70 | ||
71 | if (expected_len != out_len | |
72 | || memcmp(expected, out, out_len) != 0) | |
73 | goto err; | |
74 | ret = 1; | |
75 | err: | |
76 | EVP_MAC_CTX_free(ctx); | |
77 | EVP_MAC_free(mac); | |
78 | return ret; | |
79 | } | |
80 | ||
81 | /* This API is triggered either on loading of the FIPS module or on demand */ | |
82 | int SELF_TEST_post(SELF_TEST_POST_PARAMS *st) | |
83 | { | |
84 | int ok = 0; | |
85 | int kats_already_passed = 0; | |
86 | int on_demand_test = (FIPS_state != FIPS_STATE_INIT); | |
87 | long checksum_len; | |
88 | BIO *bio_module = NULL, *bio_indicator = NULL; | |
89 | unsigned char *module_checksum = NULL; | |
90 | unsigned char *indicator_checksum = NULL; | |
91 | ||
92 | if (st == NULL | |
93 | || FIPS_state == FIPS_STATE_ERROR | |
94 | || FIPS_state == FIPS_STATE_SELFTEST | |
95 | || st->module_checksum_data == NULL) | |
96 | goto end; | |
97 | ||
98 | module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data, | |
99 | &checksum_len); | |
100 | if (module_checksum == NULL) | |
101 | goto end; | |
102 | bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb"); | |
103 | ||
104 | /* Always check the integrity of the fips module */ | |
105 | if (bio_module == NULL | |
106 | || !verify_integrity(bio_module, st->bio_read_ex_cb, | |
107 | module_checksum, checksum_len, st->libctx)) | |
108 | goto end; | |
109 | ||
110 | /* This will be NULL during installation - so the self test KATS will run */ | |
111 | if (st->indicator_data != NULL) { | |
112 | /* | |
113 | * If the kats have already passed indicator is set - then check the | |
114 | * integrity of the indicator. | |
115 | */ | |
116 | if (st->indicator_checksum_data == NULL) | |
117 | goto end; | |
118 | indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data, | |
119 | &checksum_len); | |
120 | if (indicator_checksum == NULL) | |
121 | goto end; | |
122 | ||
123 | bio_indicator = | |
124 | (*st->bio_new_buffer_cb)(st->indicator_data, | |
125 | strlen(st->indicator_data)); | |
126 | if (bio_indicator == NULL | |
127 | || !verify_integrity(bio_indicator, st->bio_read_ex_cb, | |
128 | indicator_checksum, checksum_len, | |
129 | st->libctx)) | |
130 | goto end; | |
131 | else | |
132 | kats_already_passed = 1; | |
133 | } | |
134 | ||
135 | /* Only runs the KAT's during installation OR on_demand() */ | |
136 | if (on_demand_test || kats_already_passed == 0) { | |
137 | /*TODO (3.0) Add self test KATS */ | |
138 | } | |
139 | ok = 1; | |
140 | end: | |
141 | OPENSSL_free(module_checksum); | |
142 | OPENSSL_free(indicator_checksum); | |
143 | ||
12fca1af SL |
144 | if (st != NULL) { |
145 | (*st->bio_free_cb)(bio_indicator); | |
146 | (*st->bio_free_cb)(bio_module); | |
147 | } | |
7bb82f92 SL |
148 | FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR; |
149 | ||
150 | return ok; | |
151 | } |