1 /* 2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include "inner.h" 26 27 static void 28 cc_none0(const br_ssl_client_certificate_class **pctx) 29 { 30 (void)pctx; 31 } 32 33 static void 34 cc_none1(const br_ssl_client_certificate_class **pctx, size_t len) 35 { 36 (void)pctx; 37 (void)len; 38 } 39 40 static void 41 cc_none2(const br_ssl_client_certificate_class **pctx, 42 const unsigned char *data, size_t len) 43 { 44 (void)pctx; 45 (void)data; 46 (void)len; 47 } 48 49 static void 50 cc_choose(const br_ssl_client_certificate_class **pctx, 51 const br_ssl_client_context *cc, uint32_t auth_types, 52 br_ssl_client_certificate *choices) 53 { 54 br_ssl_client_certificate_ec_context *zc; 55 int x; 56 int scurve; 57 58 zc = (br_ssl_client_certificate_ec_context *)pctx; 59 scurve = br_ssl_client_get_server_curve(cc); 60 61 if ((zc->allowed_usages & BR_KEYTYPE_KEYX) != 0 62 && scurve == zc->sk->curve) 63 { 64 int x; 65 66 x = (zc->issuer_key_type == BR_KEYTYPE_RSA) ? 16 : 17; 67 if (((auth_types >> x) & 1) != 0) { 68 choices->auth_type = BR_AUTH_ECDH; 69 choices->hash_id = -1; 70 choices->chain = zc->chain; 71 choices->chain_len = zc->chain_len; 72 } 73 } 74 75 /* 76 * For ECDSA authentication, we must choose an appropriate 77 * hash function. 78 */ 79 x = br_ssl_choose_hash((unsigned)(auth_types >> 8)); 80 if (x == 0 || (zc->allowed_usages & BR_KEYTYPE_SIGN) == 0) { 81 memset(choices, 0, sizeof *choices); 82 return; 83 } 84 choices->auth_type = BR_AUTH_ECDSA; 85 choices->hash_id = x; 86 choices->chain = zc->chain; 87 choices->chain_len = zc->chain_len; 88 } 89 90 static uint32_t 91 cc_do_keyx(const br_ssl_client_certificate_class **pctx, 92 unsigned char *data, size_t *len) 93 { 94 br_ssl_client_certificate_ec_context *zc; 95 uint32_t r; 96 size_t xoff, xlen; 97 98 zc = (br_ssl_client_certificate_ec_context *)pctx; 99 r = zc->iec->mul(data, *len, zc->sk->x, zc->sk->xlen, zc->sk->curve); 100 xoff = zc->iec->xoff(zc->sk->curve, &xlen); 101 memmove(data, data + xoff, xlen); 102 *len = xlen; 103 return r; 104 } 105 106 static size_t 107 cc_do_sign(const br_ssl_client_certificate_class **pctx, 108 int hash_id, size_t hv_len, unsigned char *data, size_t len) 109 { 110 br_ssl_client_certificate_ec_context *zc; 111 unsigned char hv[64]; 112 const br_hash_class *hc; 113 114 zc = (br_ssl_client_certificate_ec_context *)pctx; 115 memcpy(hv, data, hv_len); 116 hc = br_multihash_getimpl(zc->mhash, hash_id); 117 if (hc == NULL) { 118 return 0; 119 } 120 if (len < 139) { 121 return 0; 122 } 123 return zc->iecdsa(zc->iec, hc, hv, zc->sk, data); 124 } 125 126 static const br_ssl_client_certificate_class ccert_vtable = { 127 sizeof(br_ssl_client_certificate_ec_context), 128 cc_none0, /* start_name_list */ 129 cc_none1, /* start_name */ 130 cc_none2, /* append_name */ 131 cc_none0, /* end_name */ 132 cc_none0, /* end_name_list */ 133 cc_choose, 134 cc_do_keyx, 135 cc_do_sign 136 }; 137 138 /* see bearssl_ssl.h */ 139 void 140 br_ssl_client_set_single_ec(br_ssl_client_context *cc, 141 const br_x509_certificate *chain, size_t chain_len, 142 const br_ec_private_key *sk, unsigned allowed_usages, 143 unsigned cert_issuer_key_type, 144 const br_ec_impl *iec, br_ecdsa_sign iecdsa) 145 { 146 cc->client_auth.single_ec.vtable = &ccert_vtable; 147 cc->client_auth.single_ec.chain = chain; 148 cc->client_auth.single_ec.chain_len = chain_len; 149 cc->client_auth.single_ec.sk = sk; 150 cc->client_auth.single_ec.allowed_usages = allowed_usages; 151 cc->client_auth.single_ec.issuer_key_type = cert_issuer_key_type; 152 cc->client_auth.single_ec.mhash = &cc->eng.mhash; 153 cc->client_auth.single_ec.iec = iec; 154 cc->client_auth.single_ec.iecdsa = iecdsa; 155 cc->client_auth_vtable = &cc->client_auth.single_ec.vtable; 156 } 157