diff options
author | Adam Langley <agl@google.com> | 2014-09-30 15:20:01 -0700 |
---|---|---|
committer | Adam Langley <agl@google.com> | 2014-09-30 15:59:52 -0700 |
commit | a029281fff6b28b379bd69602f8f5649f0a2740d (patch) | |
tree | 8081e33141e5809ee50758735c6d300975df7fa8 | |
parent | f4cb1ee4b00abbfb6f968dc25818c23b4b47e584 (diff) | |
download | ipsec-tools-a029281fff6b28b379bd69602f8f5649f0a2740d.tar.gz |
ipsec-tools: update for BoringSSL.
BoringSSL is Google's version of OpenSSL[1] with lots of things cleaned
up and removed. This change makes ipsec-tools work with both BoringSSL
and Android's existing version of OpenSSL.
Some changes are generally applicable but upstream ipsec-tools appears
to be dead. I've followed the existing practice of #ifdef'ing the
changes but, if there's no upstream, then I'd be happy to be more
aggressive about that.
Otherwise, apart from a couple of tweaks, the big changes are to the way
that the ENGINE works and to replace the PKCS#7 parsing code.
[1] https://www.imperialviolet.org/2014/06/20/boringssl.html
Change-Id: I32d7eb4e0e0a90f92cf5e8f9675dac4a8edc7a4a
-rw-r--r-- | Android.mk | 11 | ||||
-rw-r--r-- | main.c | 20 | ||||
-rw-r--r-- | src/racoon/crypto_openssl.c | 83 | ||||
-rw-r--r-- | src/racoon/ipsec_doi.c | 14 | ||||
-rw-r--r-- | src/racoon/isakmp.c | 5 | ||||
-rw-r--r-- | src/racoon/isakmp_cfg.c | 4 | ||||
-rw-r--r-- | src/racoon/isakmp_xauth.c | 3 | ||||
-rw-r--r-- | src/racoon/oakley.c | 88 |
8 files changed, 198 insertions, 30 deletions
@@ -62,9 +62,14 @@ LOCAL_STATIC_LIBRARIES := libipsec LOCAL_SHARED_LIBRARIES := libcutils liblog libcrypto +include $(TOP)/external/openssl/flavor.mk +ifeq ($(OPENSSL_FLAVOR),BoringSSL) + LOCAL_SHARED_LIBRARIES += libkeystore-engine +endif + LOCAL_CFLAGS := -DANDROID_CHANGES -DHAVE_CONFIG_H -DHAVE_OPENSSL_ENGINE_H -LOCAL_CFLAGS += -Wno-sign-compare -Wno-missing-field-initializers +LOCAL_CFLAGS += -Wno-sign-compare -Wno-missing-field-initializers -Wno-unused-parameter -Wno-pointer-sign -Werror LOCAL_MODULE := racoon @@ -78,9 +83,9 @@ LOCAL_SRC_FILES := \ src/libipsec/pfkey.c \ src/libipsec/ipsec_strerror.c -LOCAL_CFLAGS := -DHAVE_CONFIG_H -DHAVE_OPENSSL_ENGINE_H +LOCAL_CFLAGS := -DANDROID_CHANGES -DHAVE_CONFIG_H -DHAVE_OPENSSL_ENGINE_H -LOCAL_CFLAGS += -Wno-sign-compare -Wno-missing-field-initializers +LOCAL_CFLAGS += -Wno-sign-compare -Wno-missing-field-initializers -Wno-unused-parameter -Wno-pointer-sign -Werror LOCAL_C_INCLUDES += \ $(LOCAL_PATH) \ @@ -159,17 +159,22 @@ int main(int argc, char **argv) { #ifdef ANDROID_CHANGES int control = android_get_control_and_arguments(&argc, &argv); - ENGINE *e; +#if !defined(OPENSSL_IS_BORINGSSL) + ENGINE *engine; +#endif + if (control != -1) { pname = "%p"; monitor_fd(control, NULL); +#if !defined(OPENSSL_IS_BORINGSSL) ENGINE_load_dynamic(); - e = ENGINE_by_id("keystore"); - if (!e || !ENGINE_init(e)) { + engine = ENGINE_by_id("keystore"); + if (!engine || !ENGINE_init(engine)) { do_plog(LLV_ERROR, "ipsec-tools: cannot load keystore engine"); exit(1); } +#endif } #endif @@ -207,10 +212,11 @@ int main(int argc, char **argv) } } } -#ifdef ANDROID_CHANGES - if (e) { - ENGINE_finish(e); - ENGINE_free(e); + +#if !defined(OPENSSL_IS_BORINGSSL) + if (engine) { + ENGINE_finish(engine); + ENGINE_free(engine); } #endif return 0; diff --git a/src/racoon/crypto_openssl.c b/src/racoon/crypto_openssl.c index 811d0ef..3043f4c 100644 --- a/src/racoon/crypto_openssl.c +++ b/src/racoon/crypto_openssl.c @@ -113,6 +113,12 @@ typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; #include "debug.h" #include "gcmalloc.h" +#if defined(OPENSSL_IS_BORINGSSL) +/* HMAC_cleanup is deprecated wrapper in OpenSSL and has been removed in + * BoringSSL. */ +#define HMAC_cleanup(ctx) HMAC_CTX_cleanup(ctx) +#endif + /* * I hate to cast every parameter to des_xx into void *, but it is * necessary for SSLeay/OpenSSL portability. It sucks. @@ -814,7 +820,11 @@ eay_get_x509text(cert) goto end; } +#if defined(ANDROID_CHANGES) + len = BIO_get_mem_data(bio, (char**) &bp); +#else len = BIO_get_mem_data(bio, &bp); +#endif text = racoon_malloc(len + 1); if (text == NULL) goto end; @@ -1208,7 +1218,11 @@ eay_strerror() int line, flags; unsigned long es; +#if defined(ANDROID_CHANGES) + es = 0; +#else es = CRYPTO_thread_id(); +#endif while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0){ n = snprintf(ebuf + len, sizeof(ebuf) - len, @@ -1242,6 +1256,7 @@ evp_crypt(vchar_t *data, vchar_t *key, vchar_t *iv, const EVP_CIPHER *e, int enc EVP_CIPHER_CTX_init(&ctx); +#if !defined(OPENSSL_IS_BORINGSSL) switch(EVP_CIPHER_nid(e)){ case NID_bf_cbc: case NID_bf_ecb: @@ -1282,13 +1297,16 @@ evp_crypt(vchar_t *data, vchar_t *key, vchar_t *iv, const EVP_CIPHER *e, int enc } break; default: +#endif /* OPENSSL_IS_BORINGSSL */ if (!EVP_CipherInit(&ctx, e, (u_char *) key->v, (u_char *) iv->v, enc)) { OpenSSL_BUG(); vfree(res); return NULL; } +#if !defined(OPENSSL_IS_BORINGSSL) } +#endif /* disable openssl padding */ EVP_CIPHER_CTX_set_padding(&ctx, 0); @@ -1341,6 +1359,16 @@ eay_des_decrypt(data, key, iv) return evp_crypt(data, key, iv, EVP_des_cbc(), 0); } +#if defined(OPENSSL_IS_BORINGSSL) +/* BoringSSL doesn't implement DES_is_weak_key because the concept is nonsense. + * Thankfully, ipsec-tools never actually uses the result of this function. */ +static int +DES_is_weak_key(const DES_cblock *key) +{ + return 0; +} +#endif /* OPENSSL_IS_BORINGSSL */ + int eay_des_weakkey(key) vchar_t *key; @@ -1672,9 +1700,11 @@ aes_evp_by_keylen(int keylen) case 16: case 128: return EVP_aes_128_cbc(); +#if !defined(ANDROID_CHANGES) case 24: case 192: return EVP_aes_192_cbc(); +#endif case 32: case 256: return EVP_aes_256_cbc(); @@ -2447,8 +2477,13 @@ eay_dh_generate(prime, g, publen, pub, priv) if (!BN_set_word(dh->g, g)) goto end; - if (publen != 0) + if (publen != 0) { +#if defined(OPENSSL_IS_BORINGSSL) + dh->priv_length = publen; +#else dh->length = publen; +#endif + } /* generate public and private number */ if (!DH_generate_key(dh)) @@ -2496,7 +2531,11 @@ eay_dh_compute(prime, g, pub, priv, pub2, key) goto end; if (eay_v2bn(&dh->priv_key, priv) < 0) goto end; +#if defined(OPENSSL_IS_BORINGSSL) + dh->priv_length = pub2->l * 8; +#else dh->length = pub2->l * 8; +#endif dh->g = NULL; if ((dh->g = BN_new()) == NULL) @@ -2551,7 +2590,11 @@ eay_bn2v(var, bn) vchar_t **var; BIGNUM *bn; { +#if defined(ANDROID_CHANGES) + *var = vmalloc(bn->top * sizeof(BN_ULONG)); +#else *var = vmalloc(bn->top * BN_BYTES); +#endif if (*var == NULL) return(-1); @@ -2574,6 +2617,23 @@ eay_init() vchar_t * base64_decode(char *in, long inlen) { +#if defined(OPENSSL_IS_BORINGSSL) + vchar_t *res; + size_t decoded_size; + + if (!EVP_DecodedLength(&decoded_size, inlen)) { + return NULL; + } + res = vmalloc(decoded_size); + if (res == NULL) { + return NULL; + } + if (!EVP_DecodeBase64((uint8_t*) res->v, &res->l, decoded_size, (uint8_t*) in, inlen)) { + vfree(res); + return NULL; + } + return res; +#else BIO *bio=NULL, *b64=NULL; vchar_t *res = NULL; char *outb; @@ -2606,11 +2666,27 @@ out: BIO_free_all(bio); return res; +#endif } vchar_t * base64_encode(char *in, long inlen) { +#if defined(OPENSSL_IS_BORINGSSL) + vchar_t *res; + size_t encoded_size; + + if (!EVP_EncodedLength(&encoded_size, inlen)) { + return NULL; + } + res = vmalloc(encoded_size+1); + if (res == NULL) { + return NULL; + } + EVP_EncodeBlock((uint8_t*) res->v, (uint8_t*) in, inlen); + res->v[encoded_size] = 0; + return res; +#else BIO *bio=NULL, *b64=NULL; char *ptr; long plen = -1; @@ -2637,6 +2713,7 @@ out: BIO_free_all(bio); return res; +#endif } static RSA * @@ -2745,5 +2822,9 @@ eay_random() const char * eay_version() { +#if defined(OPENSSL_IS_BORINGSSL) + return "(BoringSSL)"; +#else return SSLeay_version(SSLEAY_VERSION); +#endif } diff --git a/src/racoon/ipsec_doi.c b/src/racoon/ipsec_doi.c index 0aa1843..9a59135 100644 --- a/src/racoon/ipsec_doi.c +++ b/src/racoon/ipsec_doi.c @@ -1318,7 +1318,11 @@ get_proppair(sa, mode) "failed to get buffer.\n"); goto bad; } +#if defined(ANDROID_CHANGES) + memset(pair, 0, MAXPROPPAIRLEN * sizeof(*pair)); +#else memset(pair, 0, sizeof(pair)); +#endif bp = (caddr_t)(sab + 1); tlen = sa->l - sizeof(*sab); @@ -4008,17 +4012,27 @@ set_identifier_qual(vpp, type, value, qual) BIO *bio; unsigned char *ptr = (unsigned char *) new->v, *buf; size_t len; +#if defined(ANDROID_CHANGES) + char *bio_contents; +#else char save; +#endif xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l); bio = BIO_new(BIO_s_mem()); X509_NAME_print_ex(bio, xn, 0, 0); +#if defined(ANDROID_CHANGES) + BIO_write(bio, "\x00", 1); + BIO_get_mem_data(bio, &bio_contents); + plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", bio_contents); +#else len = BIO_get_mem_data(bio, &ptr); save = ptr[len]; ptr[len] = 0; plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr); ptr[len] = save; +#endif X509_NAME_free(xn); BIO_free(bio); } diff --git a/src/racoon/isakmp.c b/src/racoon/isakmp.c index b470b54..7017f21 100644 --- a/src/racoon/isakmp.c +++ b/src/racoon/isakmp.c @@ -116,7 +116,7 @@ # ifndef SOL_UDP # define SOL_UDP 17 # endif -#ifdef ANDROID_CHANGES +#if defined(ANDROID_CHANGES) && !defined(__linux) #define __linux #endif # endif /* __linux__ */ @@ -2937,8 +2937,9 @@ log_ph1established(iph1) isakmp_pindex(&iph1->index, 0)); EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_UP, NULL); - if(!iph1->rmconf->mode_cfg) + if(!iph1->rmconf->mode_cfg) { EVT_PUSH(iph1->local, iph1->remote, EVTT_NO_ISAKMP_CFG, NULL); + } racoon_free(src); racoon_free(dst); diff --git a/src/racoon/isakmp_cfg.c b/src/racoon/isakmp_cfg.c index a9aa609..fa127dc 100644 --- a/src/racoon/isakmp_cfg.c +++ b/src/racoon/isakmp_cfg.c @@ -1841,7 +1841,11 @@ isakmp_cfg_iplist_to_str(dest, count, addr, withmask) else l = sizeof(struct in_addr); memcpy(&tmp, addr, l); +#if defined(ANDROID_CHANGES) + addr = ((uint8_t*) addr) + l; +#else addr += l; +#endif if((uint32_t)tmp.addr4.s_addr == 0) break; diff --git a/src/racoon/isakmp_xauth.c b/src/racoon/isakmp_xauth.c index a0b799d..3f62587 100644 --- a/src/racoon/isakmp_xauth.c +++ b/src/racoon/isakmp_xauth.c @@ -375,6 +375,9 @@ xauth_reply(iph1, port, id, res) struct ph1handle *iph1; int port; int id; +#if defined(ANDROID_CHANGES) + int res; +#endif { struct xauth_state *xst = &iph1->mode_cfg->xauth; char *usr = xst->authdata.generic.usr; diff --git a/src/racoon/oakley.c b/src/racoon/oakley.c index c446bbb..6cdd82a 100644 --- a/src/racoon/oakley.c +++ b/src/racoon/oakley.c @@ -38,10 +38,14 @@ #include <sys/socket.h> /* XXX for subjectaltname */ #include <netinet/in.h> /* XXX for subjectaltname */ -#include <openssl/pkcs7.h> #include <openssl/x509.h> -#ifdef ANDROID_CHANGES +#include <openssl/err.h> + +#if !defined(OPENSSL_IS_BORINGSSL) #include <openssl/engine.h> +#include <openssl/pkcs7.h> +#else +#include <openssl/bytestring.h> #endif #include <stdlib.h> @@ -1803,38 +1807,57 @@ end: #endif #ifdef ANDROID_CHANGES + +#if defined(OPENSSL_IS_BORINGSSL) +/* EVP_PKEY_from_keystore is from system/security/keystore-engine. */ +extern EVP_PKEY* EVP_PKEY_from_keystore(const char *key_id); +#endif + static vchar_t* keystore_sign(vchar_t* src, const char* path) { vchar_t* sig = NULL; + EVP_PKEY *evp = NULL; - ENGINE* e = ENGINE_by_id("keystore"); - if (!e) { +#if !defined(OPENSSL_IS_BORINGSSL) + ENGINE *engine = ENGINE_by_id("keystore"); + if (!engine) { return NULL; } - - if (!ENGINE_init(e)) { - ENGINE_free(e); + if (!ENGINE_init(engine)) { + ENGINE_free(engine); return NULL; } +#endif const char *key_id; if (sscanf(path, pname, &key_id) != 1) { do_plog(LLV_ERROR, "couldn't read private key info\n"); - return NULL; + goto out; } - EVP_PKEY* evp = ENGINE_load_private_key(e, key_id, NULL, NULL); +#if !defined(OPENSSL_IS_BORINGSSL) + evp = ENGINE_load_private_key(engine, key_id, NULL, NULL); +#else + evp = EVP_PKEY_from_keystore(key_id); +#endif if (!evp) { do_plog(LLV_ERROR, "couldn't retrieve private key"); - ERR_clear_error(); - return NULL; + ERR_remove_thread_state(NULL); + goto out; } - sig = eay_rsa_sign(src, evp->pkey.rsa); + if (EVP_PKEY_id(evp) == EVP_PKEY_RSA) { + sig = eay_rsa_sign(src, evp->pkey.rsa); + } - EVP_PKEY_free(evp); +out: + if (evp) { + EVP_PKEY_free(evp); + } - ENGINE_finish(e); - ENGINE_free(e); +#if !defined(OPENSSL_IS_BORINGSSL) + ENGINE_finish(engine); + ENGINE_free(engine); +#endif return sig; } @@ -2126,7 +2149,9 @@ oakley_savecert(iph1, gen) cert_t **c; u_int8_t type; STACK_OF(X509) *certs=NULL; +#if !defined(OPENSSL_IS_BORINGSSL) PKCS7 *p7; +#endif type = *(u_int8_t *)(gen + 1) & 0xff; @@ -2168,7 +2193,13 @@ oakley_savecert(iph1, gen) if (type == ISAKMP_CERT_PKCS7) { u_char *bp; +#if defined(OPENSSL_IS_BORINGSSL) + size_t i; + STACK_OF(X509) *certs = sk_X509_new_null(); + CBS cbs; +#else int i; +#endif /* Skip the header */ bp = (u_char *)(gen + 1); @@ -2176,7 +2207,23 @@ oakley_savecert(iph1, gen) * we know that already */ bp++; - p7 = d2i_PKCS7(NULL, (void *)&bp, +#if defined(OPENSSL_IS_BORINGSSL) + CBS_init(&cbs, bp, ntohs(gen->len) - sizeof(*gen) - 1); + if (!PKCS7_get_certificates(certs, &cbs)) { + plog(LLV_ERROR, LOCATION, NULL, + "Failed to parse PKCS#7 CERT.\n"); + sk_X509_pop_free(certs, X509_free); + return -1; + } + + if (sk_X509_num(certs) == 0) { + plog(LLV_ERROR, LOCATION, NULL, + "CERT PKCS#7 bundle contains no certs.\n"); + sk_X509_pop_free(certs, X509_free); + return -1; + } +#else + p7 = d2i_PKCS7(NULL, (void *)&bp, ntohs(gen->len) - sizeof(*gen) - 1); if (!p7) { @@ -2208,6 +2255,7 @@ oakley_savecert(iph1, gen) PKCS7_free(p7); return -1; } +#endif for (i = 0; i < sk_X509_num(certs); i++) { int len; @@ -2249,7 +2297,12 @@ oakley_savecert(iph1, gen) } break; } + +#if defined(OPENSSL_IS_BORINGSSL) + sk_X509_pop_free(certs, X509_free); +#else PKCS7_free(p7); +#endif } else { *c = save_certbuf(gen); @@ -2455,8 +2508,9 @@ oakley_getcr(iph1) plog(LLV_DEBUG, LOCATION, NULL, "create my CR: %s\n", s_isakmp_certtype(iph1->rmconf->certtype)); } - if (buf->l > 1) + if (buf->l > 1) { plogdump(LLV_DEBUG, buf->v, buf->l); + } return buf; } |