00001
00016 #include "includes.h"
00017
00018 #include "common.h"
00019 #include "base64.h"
00020 #include "crypto.h"
00021 #include "x509v3.h"
00022 #include "tlsv1_cred.h"
00023
00024
00025 struct tlsv1_credentials * tlsv1_cred_alloc(void)
00026 {
00027 struct tlsv1_credentials *cred;
00028 cred = os_zalloc(sizeof(*cred));
00029 return cred;
00030 }
00031
00032
00033 void tlsv1_cred_free(struct tlsv1_credentials *cred)
00034 {
00035 if (cred == NULL)
00036 return;
00037
00038 x509_certificate_chain_free(cred->trusted_certs);
00039 x509_certificate_chain_free(cred->cert);
00040 crypto_private_key_free(cred->key);
00041 os_free(cred->dh_p);
00042 os_free(cred->dh_g);
00043 os_free(cred);
00044 }
00045
00046
00047 static int tlsv1_add_cert_der(struct x509_certificate **chain,
00048 const u8 *buf, size_t len)
00049 {
00050 struct x509_certificate *cert;
00051 char name[128];
00052
00053 cert = x509_certificate_parse(buf, len);
00054 if (cert == NULL) {
00055 wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate",
00056 __func__);
00057 return -1;
00058 }
00059
00060 cert->next = *chain;
00061 *chain = cert;
00062
00063 x509_name_string(&cert->subject, name, sizeof(name));
00064 wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name);
00065
00066 return 0;
00067 }
00068
00069
00070 static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
00071 static const char *pem_cert_end = "-----END CERTIFICATE-----";
00072 static const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
00073 static const char *pem_key_end = "-----END RSA PRIVATE KEY-----";
00074 static const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----";
00075 static const char *pem_key2_end = "-----END PRIVATE KEY-----";
00076 static const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
00077 static const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----";
00078
00079
00080 static const u8 * search_tag(const char *tag, const u8 *buf, size_t len)
00081 {
00082 size_t i, plen;
00083
00084 plen = os_strlen(tag);
00085 if (len < plen)
00086 return NULL;
00087
00088 for (i = 0; i < len - plen; i++) {
00089 if (os_memcmp(buf + i, tag, plen) == 0)
00090 return buf + i;
00091 }
00092
00093 return NULL;
00094 }
00095
00096
00097 static int tlsv1_add_cert(struct x509_certificate **chain,
00098 const u8 *buf, size_t len)
00099 {
00100 const u8 *pos, *end;
00101 unsigned char *der;
00102 size_t der_len;
00103
00104 pos = search_tag(pem_cert_begin, buf, len);
00105 if (!pos) {
00106 wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - "
00107 "assume DER format");
00108 return tlsv1_add_cert_der(chain, buf, len);
00109 }
00110
00111 wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into "
00112 "DER format");
00113
00114 while (pos) {
00115 pos += os_strlen(pem_cert_begin);
00116 end = search_tag(pem_cert_end, pos, buf + len - pos);
00117 if (end == NULL) {
00118 wpa_printf(MSG_INFO, "TLSv1: Could not find PEM "
00119 "certificate end tag (%s)", pem_cert_end);
00120 return -1;
00121 }
00122
00123 der = base64_decode(pos, end - pos, &der_len);
00124 if (der == NULL) {
00125 wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM "
00126 "certificate");
00127 return -1;
00128 }
00129
00130 if (tlsv1_add_cert_der(chain, der, der_len) < 0) {
00131 wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM "
00132 "certificate after DER conversion");
00133 os_free(der);
00134 return -1;
00135 }
00136
00137 os_free(der);
00138
00139 end += os_strlen(pem_cert_end);
00140 pos = search_tag(pem_cert_begin, end, buf + len - end);
00141 }
00142
00143 return 0;
00144 }
00145
00146
00147 static int tlsv1_set_cert_chain(struct x509_certificate **chain,
00148 const char *cert, const u8 *cert_blob,
00149 size_t cert_blob_len)
00150 {
00151 if (cert_blob)
00152 return tlsv1_add_cert(chain, cert_blob, cert_blob_len);
00153
00154 if (cert) {
00155 u8 *buf;
00156 size_t len;
00157 int ret;
00158
00159 buf = (u8 *) os_readfile(cert, &len);
00160 if (buf == NULL) {
00161 wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
00162 cert);
00163 return -1;
00164 }
00165
00166 ret = tlsv1_add_cert(chain, buf, len);
00167 os_free(buf);
00168 return ret;
00169 }
00170
00171 return 0;
00172 }
00173
00174
00185 int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert,
00186 const u8 *cert_blob, size_t cert_blob_len,
00187 const char *path)
00188 {
00189 if (tlsv1_set_cert_chain(&cred->trusted_certs, cert,
00190 cert_blob, cert_blob_len) < 0)
00191 return -1;
00192
00193 if (path) {
00194
00195 wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory "
00196 "not yet supported");
00197 return -1;
00198 }
00199
00200 return 0;
00201 }
00202
00203
00213 int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert,
00214 const u8 *cert_blob, size_t cert_blob_len)
00215 {
00216 return tlsv1_set_cert_chain(&cred->cert, cert,
00217 cert_blob, cert_blob_len);
00218 }
00219
00220
00221 static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len)
00222 {
00223 const u8 *pos, *end;
00224 unsigned char *der;
00225 size_t der_len;
00226 struct crypto_private_key *pkey;
00227
00228 pos = search_tag(pem_key_begin, key, len);
00229 if (!pos) {
00230 pos = search_tag(pem_key2_begin, key, len);
00231 if (!pos)
00232 return NULL;
00233 pos += os_strlen(pem_key2_begin);
00234 end = search_tag(pem_key2_end, pos, key + len - pos);
00235 if (!end)
00236 return NULL;
00237 } else {
00238 pos += os_strlen(pem_key_begin);
00239 end = search_tag(pem_key_end, pos, key + len - pos);
00240 if (!end)
00241 return NULL;
00242 }
00243
00244 der = base64_decode(pos, end - pos, &der_len);
00245 if (!der)
00246 return NULL;
00247 pkey = crypto_private_key_import(der, der_len, NULL);
00248 os_free(der);
00249 return pkey;
00250 }
00251
00252
00253 static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key,
00254 size_t len,
00255 const char *passwd)
00256 {
00257 const u8 *pos, *end;
00258 unsigned char *der;
00259 size_t der_len;
00260 struct crypto_private_key *pkey;
00261
00262 if (passwd == NULL)
00263 return NULL;
00264 pos = search_tag(pem_key_enc_begin, key, len);
00265 if (!pos)
00266 return NULL;
00267 pos += os_strlen(pem_key_enc_begin);
00268 end = search_tag(pem_key_enc_end, pos, key + len - pos);
00269 if (!end)
00270 return NULL;
00271
00272 der = base64_decode(pos, end - pos, &der_len);
00273 if (!der)
00274 return NULL;
00275 pkey = crypto_private_key_import(der, der_len, passwd);
00276 os_free(der);
00277 return pkey;
00278 }
00279
00280
00281 static int tlsv1_set_key(struct tlsv1_credentials *cred,
00282 const u8 *key, size_t len, const char *passwd)
00283 {
00284 cred->key = crypto_private_key_import(key, len, passwd);
00285 if (cred->key == NULL)
00286 cred->key = tlsv1_set_key_pem(key, len);
00287 if (cred->key == NULL)
00288 cred->key = tlsv1_set_key_enc_pem(key, len, passwd);
00289 if (cred->key == NULL) {
00290 wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key");
00291 return -1;
00292 }
00293 return 0;
00294 }
00295
00296
00308 int tlsv1_set_private_key(struct tlsv1_credentials *cred,
00309 const char *private_key,
00310 const char *private_key_passwd,
00311 const u8 *private_key_blob,
00312 size_t private_key_blob_len)
00313 {
00314 crypto_private_key_free(cred->key);
00315 cred->key = NULL;
00316
00317 if (private_key_blob)
00318 return tlsv1_set_key(cred, private_key_blob,
00319 private_key_blob_len,
00320 private_key_passwd);
00321
00322 if (private_key) {
00323 u8 *buf;
00324 size_t len;
00325 int ret;
00326
00327 buf = (u8 *) os_readfile(private_key, &len);
00328 if (buf == NULL) {
00329 wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
00330 private_key);
00331 return -1;
00332 }
00333
00334 ret = tlsv1_set_key(cred, buf, len, private_key_passwd);
00335 os_free(buf);
00336 return ret;
00337 }
00338
00339 return 0;
00340 }
00341
00342
00343 static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred,
00344 const u8 *dh, size_t len)
00345 {
00346 struct asn1_hdr hdr;
00347 const u8 *pos, *end;
00348
00349 pos = dh;
00350 end = dh + len;
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 if (asn1_get_next(pos, len, &hdr) < 0 ||
00361 hdr.class != ASN1_CLASS_UNIVERSAL ||
00362 hdr.tag != ASN1_TAG_SEQUENCE) {
00363 wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a "
00364 "valid SEQUENCE - found class %d tag 0x%x",
00365 hdr.class, hdr.tag);
00366 return -1;
00367 }
00368 pos = hdr.payload;
00369
00370
00371 if (asn1_get_next(pos, end - pos, &hdr) < 0)
00372 return -1;
00373
00374 if (hdr.class != ASN1_CLASS_UNIVERSAL ||
00375 hdr.tag != ASN1_TAG_INTEGER) {
00376 wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; "
00377 "class=%d tag=0x%x", hdr.class, hdr.tag);
00378 return -1;
00379 }
00380
00381 wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length);
00382 if (hdr.length == 0)
00383 return -1;
00384 os_free(cred->dh_p);
00385 cred->dh_p = os_malloc(hdr.length);
00386 if (cred->dh_p == NULL)
00387 return -1;
00388 os_memcpy(cred->dh_p, hdr.payload, hdr.length);
00389 cred->dh_p_len = hdr.length;
00390 pos = hdr.payload + hdr.length;
00391
00392
00393 if (asn1_get_next(pos, end - pos, &hdr) < 0)
00394 return -1;
00395
00396 if (hdr.class != ASN1_CLASS_UNIVERSAL ||
00397 hdr.tag != ASN1_TAG_INTEGER) {
00398 wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; "
00399 "class=%d tag=0x%x", hdr.class, hdr.tag);
00400 return -1;
00401 }
00402
00403 wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length);
00404 if (hdr.length == 0)
00405 return -1;
00406 os_free(cred->dh_g);
00407 cred->dh_g = os_malloc(hdr.length);
00408 if (cred->dh_g == NULL)
00409 return -1;
00410 os_memcpy(cred->dh_g, hdr.payload, hdr.length);
00411 cred->dh_g_len = hdr.length;
00412
00413 return 0;
00414 }
00415
00416
00417 static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----";
00418 static const char *pem_dhparams_end = "-----END DH PARAMETERS-----";
00419
00420
00421 static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred,
00422 const u8 *buf, size_t len)
00423 {
00424 const u8 *pos, *end;
00425 unsigned char *der;
00426 size_t der_len;
00427
00428 pos = search_tag(pem_dhparams_begin, buf, len);
00429 if (!pos) {
00430 wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - "
00431 "assume DER format");
00432 return tlsv1_set_dhparams_der(cred, buf, len);
00433 }
00434
00435 wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER "
00436 "format");
00437
00438 pos += os_strlen(pem_dhparams_begin);
00439 end = search_tag(pem_dhparams_end, pos, buf + len - pos);
00440 if (end == NULL) {
00441 wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end "
00442 "tag (%s)", pem_dhparams_end);
00443 return -1;
00444 }
00445
00446 der = base64_decode(pos, end - pos, &der_len);
00447 if (der == NULL) {
00448 wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams");
00449 return -1;
00450 }
00451
00452 if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) {
00453 wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams "
00454 "DER conversion");
00455 os_free(der);
00456 return -1;
00457 }
00458
00459 os_free(der);
00460
00461 return 0;
00462 }
00463
00464
00474 int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file,
00475 const u8 *dh_blob, size_t dh_blob_len)
00476 {
00477 if (dh_blob)
00478 return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len);
00479
00480 if (dh_file) {
00481 u8 *buf;
00482 size_t len;
00483 int ret;
00484
00485 buf = (u8 *) os_readfile(dh_file, &len);
00486 if (buf == NULL) {
00487 wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
00488 dh_file);
00489 return -1;
00490 }
00491
00492 ret = tlsv1_set_dhparams_blob(cred, buf, len);
00493 os_free(buf);
00494 return ret;
00495 }
00496
00497 return 0;
00498 }
00499