X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fustream-ssl.git;a=blobdiff_plain;f=ustream-polarssl.c;h=39bde2111ce6227366107b9becae29aacfa3f0a7;hp=d55fe0439d1a5cf993b15b448fb841438a156350;hb=ec80adaa1b47f28d426fa19c692011ce60b992d6;hpb=56f5d54985e1e974711d6f602faf98a00e306364 diff --git a/ustream-polarssl.c b/ustream-polarssl.c index d55fe04..39bde21 100644 --- a/ustream-polarssl.c +++ b/ustream-polarssl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "ustream-ssl.h" #include "ustream-internal.h" @@ -60,7 +61,7 @@ static int s_ustream_write(void *ctx, const unsigned char *buf, size_t len) return ret; } -__hidden void ustream_set_io(void *ctx, void *ssl, struct ustream *conn) +__hidden void ustream_set_io(struct ustream_ssl_ctx *ctx, void *ssl, struct ustream *conn) { ssl_set_bio(ssl, s_ustream_read, conn, s_ustream_write, conn); } @@ -79,74 +80,70 @@ static bool urandom_init(void) static int _urandom(void *ctx, unsigned char *out, size_t len) { - read(urandom_fd, out, len); + if (read(urandom_fd, out, len) < 0) + return POLARSSL_ERR_ENTROPY_SOURCE_FAILED; + return 0; } -__hidden void * __ustream_ssl_context_new(bool server) +__hidden struct ustream_ssl_ctx * +__ustream_ssl_context_new(bool server) { - struct ustream_polarssl_ctx *uctx; + struct ustream_ssl_ctx *ctx; if (!urandom_init()) return NULL; - uctx = calloc(1, sizeof(*uctx)); - if (!uctx) + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) return NULL; - uctx->server = server; -#ifdef USE_VERSION_1_3 - pk_init(&uctx->key); -#else - rsa_init(&uctx->key, RSA_PKCS_V15, 0); -#endif + ctx->server = server; + pk_init(&ctx->key); + x509_crt_init(&ctx->ca_cert); + x509_crt_init(&ctx->cert); + + return ctx; +} + +__hidden int __ustream_ssl_add_ca_crt_file(struct ustream_ssl_ctx *ctx, const char *file) +{ + int ret; + + ret = x509_crt_parse_file(&ctx->ca_cert, file); + if (ret) + return -1; - return uctx; + return 0; } -__hidden int __ustream_ssl_set_crt_file(void *ctx, const char *file) +__hidden int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char *file) { - struct ustream_polarssl_ctx *uctx = ctx; int ret; -#ifdef USE_VERSION_1_3 - ret = x509_crt_parse_file(&uctx->cert, file); -#else - ret = x509parse_crtfile(&uctx->cert, file); -#endif + ret = x509_crt_parse_file(&ctx->cert, file); if (ret) return -1; return 0; } -__hidden int __ustream_ssl_set_key_file(void *ctx, const char *file) +__hidden int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char *file) { - struct ustream_polarssl_ctx *uctx = ctx; int ret; -#ifdef USE_VERSION_1_3 - ret = pk_parse_keyfile(&uctx->key, file, NULL); -#else - ret = x509parse_keyfile(&uctx->key, file, NULL); -#endif + ret = pk_parse_keyfile(&ctx->key, file, NULL); if (ret) return -1; return 0; } -__hidden void __ustream_ssl_context_free(void *ctx) +__hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx) { - struct ustream_polarssl_ctx *uctx = ctx; - -#ifdef USE_VERSION_1_3 - pk_free(&uctx->key); - x509_crt_free(&uctx->cert); -#else - rsa_free(&uctx->key); - x509_free(&uctx->cert); -#endif + pk_free(&ctx->key); + x509_crt_free(&ctx->ca_cert); + x509_crt_free(&ctx->cert); free(ctx); } @@ -167,14 +164,46 @@ static bool ssl_do_wait(int ret) } } +static void ustream_ssl_verify_cert(struct ustream_ssl *us) +{ + void *ssl = us->ssl; + const char *msg = NULL; + bool cn_mismatch; + int r; + + r = ssl_get_verify_result(ssl); + cn_mismatch = r & BADCERT_CN_MISMATCH; + r &= ~BADCERT_CN_MISMATCH; + + if (r & BADCERT_EXPIRED) + msg = "certificate has expired"; + else if (r & BADCERT_REVOKED) + msg = "certificate has been revoked"; + else if (r & BADCERT_NOT_TRUSTED) + msg = "certificate is self-signed or not signed by a trusted CA"; + else + msg = "unknown error"; + + if (r) { + if (us->notify_verify_error) + us->notify_verify_error(us, r, msg); + return; + } + + if (!cn_mismatch) + us->valid_cn = true; +} + __hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us) { void *ssl = us->ssl; int r; r = ssl_handshake(ssl); - if (r == 0) + if (r == 0) { + ustream_ssl_verify_cert(us); return U_SSL_OK; + } if (ssl_do_wait(r)) return U_SSL_PENDING; @@ -186,17 +215,23 @@ __hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us) __hidden int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len) { void *ssl = us->ssl; - int ret = ssl_write(ssl, (const unsigned char *) buf, len); + int done = 0, ret = 0; - if (ret < 0) { - if (ssl_do_wait(ret)) - return 0; + while (done != len) { + ret = ssl_write(ssl, (const unsigned char *) buf + done, len - done); - ustream_ssl_error(us, ret); - return -1; + if (ret < 0) { + if (ssl_do_wait(ret)) + return done; + + ustream_ssl_error(us, ret); + return -1; + } + + done += ret; } - return ret; + return done; } __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len) @@ -207,6 +242,9 @@ __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len) if (ssl_do_wait(ret)) return U_SSL_PENDING; + if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) + return 0; + ustream_ssl_error(us, ret); return U_SSL_ERROR; } @@ -214,53 +252,43 @@ __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len) return ret; } +#define TLS_DEFAULT_CIPHERS \ + TLS_CIPHER(AES_256_CBC_SHA256) \ + TLS_CIPHER(AES_256_GCM_SHA384) \ + TLS_CIPHER(AES_256_CBC_SHA) \ + TLS_CIPHER(CAMELLIA_256_CBC_SHA256) \ + TLS_CIPHER(CAMELLIA_256_CBC_SHA) \ + TLS_CIPHER(AES_128_CBC_SHA256) \ + TLS_CIPHER(AES_128_GCM_SHA256) \ + TLS_CIPHER(AES_128_CBC_SHA) \ + TLS_CIPHER(CAMELLIA_128_CBC_SHA256) \ + TLS_CIPHER(CAMELLIA_128_CBC_SHA) \ + TLS_CIPHER(3DES_EDE_CBC_SHA) + +static const int default_ciphersuites_nodhe[] = +{ +#define TLS_CIPHER(v) \ + TLS_RSA_WITH_##v, + TLS_DEFAULT_CIPHERS +#undef TLS_CIPHER + 0 +}; + static const int default_ciphersuites[] = { -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_AES_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) - TLS_RSA_WITH_AES_256_GCM_SHA384, -#endif /* POLARSSL_SHA2_C */ - TLS_RSA_WITH_AES_256_CBC_SHA, -#endif -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ - TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, -#endif -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_AES_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_AES_128_GCM_SHA256, -#endif /* POLARSSL_SHA2_C */ - TLS_RSA_WITH_AES_128_CBC_SHA, -#endif -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ - TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, -#endif -#if defined(POLARSSL_DES_C) - TLS_RSA_WITH_3DES_EDE_CBC_SHA, -#endif -#if defined(POLARSSL_ARC4_C) - TLS_RSA_WITH_RC4_128_SHA, - TLS_RSA_WITH_RC4_128_MD5, -#endif - 0 +#define TLS_CIPHER(v) \ + TLS_DHE_RSA_WITH_##v, \ + TLS_RSA_WITH_##v, + TLS_DEFAULT_CIPHERS +#undef TLS_CIPHER + 0 }; -__hidden void *__ustream_ssl_session_new(void *ctx) +__hidden void *__ustream_ssl_session_new(struct ustream_ssl_ctx *ctx) { - struct ustream_polarssl_ctx *uctx = ctx; ssl_context *ssl; - int ep, auth; + int auth; + int ep; ssl = calloc(1, sizeof(ssl_context)); if (!ssl) @@ -271,7 +299,7 @@ __hidden void *__ustream_ssl_session_new(void *ctx) return NULL; } - if (uctx->server) { + if (ctx->server) { ep = SSL_IS_SERVER; auth = SSL_VERIFY_NONE; } else { @@ -279,15 +307,18 @@ __hidden void *__ustream_ssl_session_new(void *ctx) auth = SSL_VERIFY_OPTIONAL; } - ssl_set_ciphersuites(ssl, default_ciphersuites); ssl_set_endpoint(ssl, ep); ssl_set_authmode(ssl, auth); ssl_set_rng(ssl, _urandom, NULL); - if (uctx->server) { - if (uctx->cert.next) - ssl_set_ca_chain(ssl, uctx->cert.next, NULL, NULL); - ssl_set_own_cert(ssl, &uctx->cert, &uctx->key); + if (ctx->server) { + ssl_set_ciphersuites(ssl, default_ciphersuites_nodhe); + if (ctx->cert.next) + ssl_set_ca_chain(ssl, ctx->cert.next, NULL, NULL); + ssl_set_own_cert(ssl, &ctx->cert, &ctx->key); + } else { + ssl_set_ciphersuites(ssl, default_ciphersuites); + ssl_set_ca_chain(ssl, &ctx->ca_cert, NULL, NULL); } ssl_session_reset(ssl); @@ -300,3 +331,10 @@ __hidden void __ustream_ssl_session_free(void *ssl) ssl_free(ssl); free(ssl); } + +__hidden void __ustream_ssl_update_peer_cn(struct ustream_ssl *us) +{ + struct ustream_ssl_ctx *ctx = us->ctx; + + ssl_set_ca_chain(us->ssl, &ctx->ca_cert, NULL, us->peer_cn); +}