tlsv1_cred.c

Go to the documentation of this file.
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                 /* TODO: add support for reading number of certificate files */
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          * DHParameter ::= SEQUENCE {
00354          *   prime INTEGER, -- p
00355          *   base INTEGER, -- g
00356          *   privateValueLength INTEGER OPTIONAL }
00357          */
00358 
00359         /* DHParamer ::= SEQUENCE */
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         /* prime INTEGER */
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         /* base INTEGER */
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:53 2009 for hostapd by  doxygen 1.6.1