|
34 | 34 | #include "../deps/picotest/picotest.h"
|
35 | 35 | #include "test.h"
|
36 | 36 |
|
| 37 | +typedef struct st_ptls_mbedtls_signature_scheme_t { |
| 38 | + uint16_t scheme_id; |
| 39 | + psa_algorithm_t hash_algo; |
| 40 | +} ptls_mbedtls_signature_scheme_t; |
| 41 | + |
| 42 | +typedef struct st_ptls_mbedtls_sign_certificate_t { |
| 43 | + ptls_sign_certificate_t super; |
| 44 | + mbedtls_svc_key_id_t key_id; |
| 45 | + psa_key_attributes_t attributes; |
| 46 | + const ptls_mbedtls_signature_scheme_t *schemes; |
| 47 | +} ptls_mbedtls_sign_certificate_t; |
| 48 | + |
| 49 | +int ptls_mbedtls_sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, ptls_async_job_t **async, |
| 50 | + uint16_t *selected_algorithm, ptls_buffer_t *outbuf, ptls_iovec_t input, |
| 51 | + const uint16_t *algorithms, size_t num_algorithms); |
| 52 | + |
37 | 53 | static int random_trial()
|
38 | 54 | {
|
39 | 55 | /* The random test is just trying to check that we call the API properly.
|
@@ -89,6 +105,157 @@ static void test_key_exchanges(void)
|
89 | 105 | subtest("x25519", test_x25519);
|
90 | 106 | }
|
91 | 107 |
|
| 108 | +/* |
| 109 | +Sign certificate implements a callback: |
| 110 | +
|
| 111 | +if ((ret = tls->ctx->sign_certificate->cb( |
| 112 | +tls->ctx->sign_certificate, tls, tls->is_server ? &tls->server.async_job : NULL, &algo, sendbuf, |
| 113 | +ptls_iovec_init(data, datalen), signature_algorithms != NULL ? signature_algorithms->list : NULL, |
| 114 | +signature_algorithms != NULL ? signature_algorithms->count : 0)) != 0) { |
| 115 | +
|
| 116 | +or: |
| 117 | +
|
| 118 | +static int sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, ptls_async_job_t **async, uint16_t *selected_algorithm, |
| 119 | +ptls_buffer_t *outbuf, ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms) |
| 120 | +
|
| 121 | +The callback "super" type is ptls_sign_certificate_t, defined by the macro: |
| 122 | +PTLS_CALLBACK_TYPE(int, sign_certificate, ptls_t *tls, ptls_async_job_t **async, uint16_t *selected_algorithm, |
| 123 | +ptls_buffer_t *output, ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms); |
| 124 | +
|
| 125 | +The notation is simple: input buffer and supported algorithms as input, selected algo and output buffer as output. |
| 126 | +Output buffer is already partially filled. |
| 127 | +
|
| 128 | +*/ |
| 129 | + |
| 130 | +#define ASSET_RSA_KEY "t/assets/rsa/key.pem" |
| 131 | +#define ASSET_RSA_PKCS8_KEY "t/assets/rsa-pkcs8/key.pem" |
| 132 | +#define ASSET_SECP256R1_KEY "t/assets/secp256r1/key.pem" |
| 133 | +#define ASSET_SECP384R1_KEY "t/assets/secp384r1/key.pem" |
| 134 | +#define ASSET_SECP521R1_KEY "t/assets/secp521r1/key.pem" |
| 135 | +#define ASSET_SECP256R1_PKCS8_KEY "t/assets/secp256r1-pkcs8/key.pem" |
| 136 | + |
| 137 | +int test_load_one_der_key(char const *path) |
| 138 | +{ |
| 139 | + int ret = -1; |
| 140 | + unsigned char hash[32]; |
| 141 | + const unsigned char h0[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, |
| 142 | + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; |
| 143 | + ptls_context_t ctx = {0}; |
| 144 | + |
| 145 | + ret = ptls_mbedtls_load_private_key(&ctx, path); |
| 146 | + if (ret != 0) { |
| 147 | + printf("Cannot create sign_certificate from: %s\n", path); |
| 148 | + ret = -1; |
| 149 | + } else if (ctx.sign_certificate == NULL) { |
| 150 | + printf("Sign_certificate not set in ptls context for: %s\n", path); |
| 151 | + ret = -1; |
| 152 | + } else { |
| 153 | + /* Try to sign something */ |
| 154 | + int ret; |
| 155 | + ptls_mbedtls_sign_certificate_t *signer = |
| 156 | + (ptls_mbedtls_sign_certificate_t *)(((unsigned char *)ctx.sign_certificate) - |
| 157 | + offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); |
| 158 | + /* get the key algorithm */ |
| 159 | + ptls_buffer_t outbuf; |
| 160 | + uint8_t outbuf_smallbuf[256]; |
| 161 | + ptls_iovec_t input = {hash, sizeof(hash)}; |
| 162 | + uint16_t selected_algorithm = 0; |
| 163 | + int num_algorithms = 0; |
| 164 | + uint16_t algorithms[16]; |
| 165 | + memcpy(hash, h0, 32); |
| 166 | + while (signer->schemes[num_algorithms].scheme_id != UINT16_MAX && num_algorithms < 16) { |
| 167 | + algorithms[num_algorithms] = signer->schemes[num_algorithms].scheme_id; |
| 168 | + num_algorithms++; |
| 169 | + } |
| 170 | + |
| 171 | + ptls_buffer_init(&outbuf, outbuf_smallbuf, sizeof(outbuf_smallbuf)); |
| 172 | + |
| 173 | + ret = ptls_mbedtls_sign_certificate(ctx.sign_certificate, NULL, NULL, &selected_algorithm, &outbuf, input, algorithms, |
| 174 | + num_algorithms); |
| 175 | + if (ret == 0) { |
| 176 | + printf("Signed a message, key: %s, scheme: %x, signature size: %zu\n", path, selected_algorithm, outbuf.off); |
| 177 | + } else { |
| 178 | + printf("Sign failed, key: %s, scheme: %x, signature size: %zu\n", path, selected_algorithm, outbuf.off); |
| 179 | + } |
| 180 | + ptls_buffer_dispose(&outbuf); |
| 181 | + ptls_mbedtls_dispose_sign_certificate(&signer->super); |
| 182 | + } |
| 183 | + return ret; |
| 184 | +} |
| 185 | + |
| 186 | +static void test_load_rsa_key() |
| 187 | +{ |
| 188 | + int ret = test_load_one_der_key(ASSET_RSA_KEY); |
| 189 | + |
| 190 | + if (ret != 0) { |
| 191 | + ok(!"fail"); |
| 192 | + return; |
| 193 | + } |
| 194 | + ok(!!"success"); |
| 195 | +} |
| 196 | + |
| 197 | +static void test_load_secp256r1_key() |
| 198 | +{ |
| 199 | + int ret = test_load_one_der_key(ASSET_SECP256R1_KEY); |
| 200 | + if (ret != 0) { |
| 201 | + ok(!"fail"); |
| 202 | + return; |
| 203 | + } |
| 204 | + ok(!!"success"); |
| 205 | +} |
| 206 | + |
| 207 | +static void test_load_secp384r1_key() |
| 208 | +{ |
| 209 | + int ret = test_load_one_der_key(ASSET_SECP384R1_KEY); |
| 210 | + if (ret != 0) { |
| 211 | + ok(!"fail"); |
| 212 | + return; |
| 213 | + } |
| 214 | + ok(!!"success"); |
| 215 | +} |
| 216 | + |
| 217 | +static void test_load_secp521r1_key() |
| 218 | +{ |
| 219 | + int ret = test_load_one_der_key(ASSET_SECP521R1_KEY); |
| 220 | + if (ret != 0) { |
| 221 | + ok(!"fail"); |
| 222 | + return; |
| 223 | + } |
| 224 | + ok(!!"success"); |
| 225 | +} |
| 226 | + |
| 227 | +static void test_load_secp256r1_pkcs8_key() |
| 228 | +{ |
| 229 | + int ret = test_load_one_der_key(ASSET_SECP256R1_PKCS8_KEY); |
| 230 | + if (ret != 0) { |
| 231 | + ok(!"fail"); |
| 232 | + return; |
| 233 | + } |
| 234 | + ok(!!"success"); |
| 235 | +} |
| 236 | + |
| 237 | +static void test_load_rsa_pkcs8_key() |
| 238 | +{ |
| 239 | + int ret = test_load_one_der_key(ASSET_RSA_PKCS8_KEY); |
| 240 | + if (ret != 0) { |
| 241 | + ok(!"fail"); |
| 242 | + return; |
| 243 | + } |
| 244 | + ok(!!"success"); |
| 245 | +} |
| 246 | + |
| 247 | +void test_sign_certificate(void) |
| 248 | +{ |
| 249 | + subtest("load rsa key", test_load_rsa_key); |
| 250 | + subtest("load secp256r1 key", test_load_secp256r1_key); |
| 251 | + subtest("load secp384r1 key", test_load_secp384r1_key); |
| 252 | + subtest("load secp521r1 key", test_load_secp521r1_key); |
| 253 | + subtest("load secp521r1-pkcs8 key", test_load_secp256r1_pkcs8_key); |
| 254 | + subtest("load rsa-pkcs8 key", test_load_rsa_pkcs8_key); |
| 255 | + |
| 256 | + /* we do not test EDDSA keys, because they are not yet supported */ |
| 257 | +} |
| 258 | + |
92 | 259 | DEFINE_FFX_AES128_ALGORITHMS(mbedtls);
|
93 | 260 | DEFINE_FFX_CHACHA20_ALGORITHMS(mbedtls);
|
94 | 261 |
|
@@ -143,6 +310,9 @@ int main(int argc, char **argv)
|
143 | 310 | ctx_peer = &mbedtls_ctx;
|
144 | 311 | subtest("minicrypto vs.", test_picotls);
|
145 | 312 |
|
| 313 | + /* test the sign certificate */ |
| 314 | + subtest("sign certificate", test_sign_certificate); |
| 315 | + |
146 | 316 | /* Deinitialize the PSA crypto library. */
|
147 | 317 | mbedtls_psa_crypto_free();
|
148 | 318 |
|
|
0 commit comments