X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fd1_srtp.c;h=e49aea9be1e4bf5866d47834c1b976819e1e4375;hp=ac1bef00ac589095c2af6606b8569fa1c58fb127;hb=fbdf0299dc98bc611d854c0a62c6ab1810d856fc;hpb=e659eff2c0ac6da05dd968a9354c9a69ca7f57b4;ds=sidebyside diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c index ac1bef00ac..e49aea9be1 100644 --- a/ssl/d1_srtp.c +++ b/ssl/d1_srtp.c @@ -1,25 +1,24 @@ -/* ssl/t1_lib.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. - * + * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * + * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,10 +33,10 @@ * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from + * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * + * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -49,7 +48,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence @@ -63,7 +62,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -109,354 +108,320 @@ * */ /* - DTLS code by Eric Rescorla - - Copyright (C) 2006, Network Resonance, Inc. - Copyright (C) 2011, RTFM, Inc. -*/ - -#ifndef OPENSSL_NO_SRTP + * DTLS code by Eric Rescorla + * + * Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc. + */ #include #include #include "ssl_locl.h" -#include "srtp.h" +#ifndef OPENSSL_NO_SRTP -static SRTP_PROTECTION_PROFILE srtp_known_profiles[]= - { +static SRTP_PROTECTION_PROFILE srtp_known_profiles[] = { { - "SRTP_AES128_CM_SHA1_80", - SRTP_AES128_CM_SHA1_80, - }, + "SRTP_AES128_CM_SHA1_80", + SRTP_AES128_CM_SHA1_80, + }, { - "SRTP_AES128_CM_SHA1_32", - SRTP_AES128_CM_SHA1_32, - }, -#if 0 + "SRTP_AES128_CM_SHA1_32", + SRTP_AES128_CM_SHA1_32, + }, { - "SRTP_NULL_SHA1_80", - SRTP_NULL_SHA1_80, - }, + "SRTP_AEAD_AES_128_GCM", + SRTP_AEAD_AES_128_GCM + }, { - "SRTP_NULL_SHA1_32", - SRTP_NULL_SHA1_32, - }, -#endif + "SRTP_AEAD_AES_256_GCM", + SRTP_AEAD_AES_256_GCM + }, {0} - }; +}; static int find_profile_by_name(char *profile_name, - SRTP_PROTECTION_PROFILE **pptr,unsigned len) - { - SRTP_PROTECTION_PROFILE *p; - - p=srtp_known_profiles; - while(p->name) - { - if((len == strlen(p->name)) && !strncmp(p->name,profile_name, - len)) - { - *pptr=p; - return 0; - } - - p++; - } - - return 1; - } - -static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTECTION_PROFILE) **out) - { - STACK_OF(SRTP_PROTECTION_PROFILE) *profiles; - - char *col; - char *ptr=(char *)profiles_string; - - SRTP_PROTECTION_PROFILE *p; - - if(!(profiles=sk_SRTP_PROTECTION_PROFILE_new_null())) - { - SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES); - return 1; - } - - do - { - col=strchr(ptr,':'); - - if(!find_profile_by_name(ptr,&p, - col ? col-ptr : (int)strlen(ptr))) - { - if (sk_SRTP_PROTECTION_PROFILE_find(profiles,p) >= 0) - { - SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - sk_SRTP_PROTECTION_PROFILE_free(profiles); - return 1; - } - - sk_SRTP_PROTECTION_PROFILE_push(profiles,p); - } - else - { - SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE); - sk_SRTP_PROTECTION_PROFILE_free(profiles); - return 1; - } - - if(col) ptr=col+1; - } while (col); - - *out=profiles; - - return 0; - } - -int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,const char *profiles) - { - return ssl_ctx_make_profiles(profiles,&ctx->srtp_profiles); - } - -int SSL_set_tlsext_use_srtp(SSL *s,const char *profiles) - { - return ssl_ctx_make_profiles(profiles,&s->srtp_profiles); - } - + SRTP_PROTECTION_PROFILE **pptr, unsigned len) +{ + SRTP_PROTECTION_PROFILE *p; + + p = srtp_known_profiles; + while (p->name) { + if ((len == strlen(p->name)) + && strncmp(p->name, profile_name, len) == 0) { + *pptr = p; + return 0; + } + + p++; + } + + return 1; +} + +static int ssl_ctx_make_profiles(const char *profiles_string, + STACK_OF(SRTP_PROTECTION_PROFILE) **out) +{ + STACK_OF(SRTP_PROTECTION_PROFILE) *profiles; + + char *col; + char *ptr = (char *)profiles_string; + SRTP_PROTECTION_PROFILE *p; + + if ((profiles = sk_SRTP_PROTECTION_PROFILE_new_null()) == NULL) { + SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, + SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES); + return 1; + } + + do { + col = strchr(ptr, ':'); + + if (!find_profile_by_name(ptr, &p, + col ? col - ptr : (int)strlen(ptr))) { + if (sk_SRTP_PROTECTION_PROFILE_find(profiles, p) >= 0) { + SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + sk_SRTP_PROTECTION_PROFILE_free(profiles); + return 1; + } + + sk_SRTP_PROTECTION_PROFILE_push(profiles, p); + } else { + SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, + SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE); + sk_SRTP_PROTECTION_PROFILE_free(profiles); + return 1; + } + + if (col) + ptr = col + 1; + } while (col); + + sk_SRTP_PROTECTION_PROFILE_free(*out); + + *out = profiles; + + return 0; +} + +int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles) +{ + return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles); +} + +int SSL_set_tlsext_use_srtp(SSL *s, const char *profiles) +{ + return ssl_ctx_make_profiles(profiles, &s->srtp_profiles); +} STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *s) - { - if(s != NULL) - { - if(s->srtp_profiles != NULL) - { - return s->srtp_profiles; - } - else if((s->ctx != NULL) && - (s->ctx->srtp_profiles != NULL)) - { - return s->ctx->srtp_profiles; - } - } - - return NULL; - } +{ + if (s != NULL) { + if (s->srtp_profiles != NULL) { + return s->srtp_profiles; + } else if ((s->ctx != NULL) && (s->ctx->srtp_profiles != NULL)) { + return s->ctx->srtp_profiles; + } + } + + return NULL; +} SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s) - { - return s->srtp_profile; - } - -/* Note: this function returns 0 length if there are no - profiles specified */ -int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen) - { - int ct=0; - int i; - STACK_OF(SRTP_PROTECTION_PROFILE) *clnt=0; - SRTP_PROTECTION_PROFILE *prof; - - clnt=SSL_get_srtp_profiles(s); - ct=sk_SRTP_PROTECTION_PROFILE_num(clnt); /* -1 if clnt == 0 */ - - if(p) - { - if(ct==0) - { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT,SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST); - return 1; - } - - if((2 + ct*2 + 1) > maxlen) - { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT,SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG); - return 1; - } - - /* Add the length */ - s2n(ct * 2, p); - for(i=0;iid,p); - } - - /* Add an empty use_mki value */ - *p++ = 0; - } - - *len=2 + ct*2 + 1; - - return 0; - } - - -int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al) - { - SRTP_PROTECTION_PROFILE *sprof; - STACK_OF(SRTP_PROTECTION_PROFILE) *srvr; - int ct; - int mki_len; - int i, srtp_pref; - unsigned int id; - - /* Length value + the MKI length */ - if(len < 3) - { - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al=SSL_AD_DECODE_ERROR; - return 1; - } - - /* Pull off the length of the cipher suite list */ - n2s(d, ct); - len -= 2; - - /* Check that it is even */ - if(ct%2) - { - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al=SSL_AD_DECODE_ERROR; - return 1; - } - - /* Check that lengths are consistent */ - if(len < (ct + 1)) - { - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al=SSL_AD_DECODE_ERROR; - return 1; - } - - srvr=SSL_get_srtp_profiles(s); - s->srtp_profile = NULL; - /* Search all profiles for a match initially */ - srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr); - - while(ct) - { - n2s(d,id); - ct-=2; - len-=2; - - /* - * Only look for match in profiles of higher preference than - * current match. - * If no profiles have been have been configured then this - * does nothing. - */ - for (i = 0; i < srtp_pref; i++) - { - sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i); - if (sprof->id == id) - { - s->srtp_profile = sprof; - srtp_pref = i; - break; - } - } - } - - /* Now extract the MKI value as a sanity check, but discard it for now */ - mki_len = *d; - d++; len--; - - if (mki_len != len) - { - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_MKI_VALUE); - *al=SSL_AD_DECODE_ERROR; - return 1; - } - - return 0; - } - -int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen) - { - if(p) - { - if(maxlen < 5) - { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT,SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG); - return 1; - } - - if(s->srtp_profile==0) - { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT,SSL_R_USE_SRTP_NOT_NEGOTIATED); - return 1; - } - s2n(2, p); - s2n(s->srtp_profile->id,p); - *p++ = 0; - } - *len=5; - - return 0; - } - - -int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al) - { - unsigned id; - int i; - int ct; - - STACK_OF(SRTP_PROTECTION_PROFILE) *clnt; - SRTP_PROTECTION_PROFILE *prof; - - if(len!=5) - { - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al=SSL_AD_DECODE_ERROR; - return 1; - } - - n2s(d, ct); - if(ct!=2) - { - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al=SSL_AD_DECODE_ERROR; - return 1; - } - - n2s(d,id); - if (*d) /* Must be no MKI, since we never offer one */ - { - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_MKI_VALUE); - *al=SSL_AD_ILLEGAL_PARAMETER; - return 1; - } - - clnt=SSL_get_srtp_profiles(s); - - /* Throw an error if the server gave us an unsolicited extension */ - if (clnt == NULL) - { - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_NO_SRTP_PROFILES); - *al=SSL_AD_DECODE_ERROR; - return 1; - } - - /* Check to see if the server gave us something we support - (and presumably offered) - */ - for(i=0;iid == id) - { - s->srtp_profile=prof; - *al=0; - return 0; - } - } - - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al=SSL_AD_DECODE_ERROR; - return 1; - } +{ + return s->srtp_profile; +} +/* + * Note: this function returns 0 length if there are no profiles specified + */ +int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, + int maxlen) +{ + int ct = 0; + int i; + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = 0; + SRTP_PROTECTION_PROFILE *prof; + + clnt = SSL_get_srtp_profiles(s); + ct = sk_SRTP_PROTECTION_PROFILE_num(clnt); /* -1 if clnt == 0 */ + + if (p) { + if (ct == 0) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT, + SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST); + return 1; + } + + if ((2 + ct * 2 + 1) > maxlen) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT, + SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG); + return 1; + } + + /* Add the length */ + s2n(ct * 2, p); + for (i = 0; i < ct; i++) { + prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i); + s2n(prof->id, p); + } + + /* Add an empty use_mki value */ + *p++ = 0; + } + + *len = 2 + ct * 2 + 1; + + return 0; +} + +int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al) +{ + SRTP_PROTECTION_PROFILE *sprof; + STACK_OF(SRTP_PROTECTION_PROFILE) *srvr; + unsigned int ct, mki_len, id; + int i, srtp_pref; + PACKET subpkt; + + /* Pull off the length of the cipher suite list and check it is even */ + if (!PACKET_get_net_2(pkt, &ct) + || (ct & 1) != 0 + || !PACKET_get_sub_packet(pkt, &subpkt, ct)) { + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + *al = SSL_AD_DECODE_ERROR; + return 1; + } + + srvr = SSL_get_srtp_profiles(s); + s->srtp_profile = NULL; + /* Search all profiles for a match initially */ + srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr); + + while (PACKET_remaining(&subpkt)) { + if (!PACKET_get_net_2(&subpkt, &id)) { + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + *al = SSL_AD_DECODE_ERROR; + return 1; + } + + /* + * Only look for match in profiles of higher preference than + * current match. + * If no profiles have been have been configured then this + * does nothing. + */ + for (i = 0; i < srtp_pref; i++) { + sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i); + if (sprof->id == id) { + s->srtp_profile = sprof; + srtp_pref = i; + break; + } + } + } + + /* + * Now extract the MKI value as a sanity check, but discard it for now + */ + if (!PACKET_get_1(pkt, &mki_len)) { + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + *al = SSL_AD_DECODE_ERROR; + return 1; + } + + if (!PACKET_forward(pkt, mki_len) + || PACKET_remaining(pkt)) { + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, + SSL_R_BAD_SRTP_MKI_VALUE); + *al = SSL_AD_DECODE_ERROR; + return 1; + } + + return 0; +} + +int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, + int maxlen) +{ + if (p) { + if (maxlen < 5) { + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT, + SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG); + return 1; + } + + if (s->srtp_profile == 0) { + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT, + SSL_R_USE_SRTP_NOT_NEGOTIATED); + return 1; + } + s2n(2, p); + s2n(s->srtp_profile->id, p); + *p++ = 0; + } + *len = 5; + + return 0; +} + +int ssl_parse_serverhello_use_srtp_ext(SSL *s, PACKET *pkt, int *al) +{ + unsigned int id, ct, mki; + int i; + + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt; + SRTP_PROTECTION_PROFILE *prof; + + if (!PACKET_get_net_2(pkt, &ct) + || ct != 2 + || !PACKET_get_net_2(pkt, &id) + || !PACKET_get_1(pkt, &mki) + || PACKET_remaining(pkt) != 0) { + SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + *al = SSL_AD_DECODE_ERROR; + return 1; + } + + if (mki != 0) { + /* Must be no MKI, since we never offer one */ + SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, + SSL_R_BAD_SRTP_MKI_VALUE); + *al = SSL_AD_ILLEGAL_PARAMETER; + return 1; + } + + clnt = SSL_get_srtp_profiles(s); + + /* Throw an error if the server gave us an unsolicited extension */ + if (clnt == NULL) { + SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, + SSL_R_NO_SRTP_PROFILES); + *al = SSL_AD_DECODE_ERROR; + return 1; + } + + /* + * Check to see if the server gave us something we support (and + * presumably offered) + */ + for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) { + prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i); + + if (prof->id == id) { + s->srtp_profile = prof; + *al = 0; + return 0; + } + } + + SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + *al = SSL_AD_DECODE_ERROR; + return 1; +} #endif