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