Implement Supported Elliptic Curves Extension.
[openssl.git] / ssl / t1_lib.c
index b248dab36171d8e01303149d8dfe5541720fbf6b..ec5f33235cd7b9799c8b22c9a633de655e5751ea 100644 (file)
@@ -181,6 +181,47 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                memcpy(ret, s->tlsext_hostname, size_str);
                ret+=size_str;
                }
+#ifndef OPENSSL_NO_EC
+       if (s->tlsext_ecpointformatlist != NULL)
+               {
+               /* Add TLS extension ECPointFormats to the ClientHello message */
+               long lenmax; 
+
+               if ((lenmax = limit - p - 5) < 0) return NULL; 
+               if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
+               if (s->tlsext_ecpointformatlist_length > 255)
+                       {
+                       SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+                       return NULL;
+                       }
+               
+               s2n(TLSEXT_TYPE_ec_point_formats,ret);
+               s2n(s->tlsext_ecpointformatlist_length + 1,ret);
+               *(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
+               memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
+               ret+=s->tlsext_ecpointformatlist_length;
+               }
+       if (s->tlsext_ellipticcurvelist != NULL)
+               {
+               /* Add TLS extension EllipticCurves to the ClientHello message */
+               long lenmax; 
+
+               if ((lenmax = limit - p - 5) < 0) return NULL; 
+               if (s->tlsext_ellipticcurvelist_length > (unsigned long)lenmax) return NULL;
+               if (s->tlsext_ellipticcurvelist_length > 255)
+                       {
+                       SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+                       return NULL;
+                       }
+               
+               s2n(TLSEXT_TYPE_elliptic_curves,ret);
+               s2n(s->tlsext_ellipticcurvelist_length + 2,ret);
+               *(ret++) = (unsigned char) ((s->tlsext_ellipticcurvelist_length >> 8) & 0xFF);
+               *(ret++) = (unsigned char) (s->tlsext_ellipticcurvelist_length & 0xFF);
+               memcpy(ret, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
+               ret+=s->tlsext_ellipticcurvelist_length;
+               }
+#endif /* OPENSSL_NO_EC */
 
        if ((extdatalen = ret-p-2)== 0) 
                return p;
@@ -193,21 +234,39 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
        {
        int extdatalen=0;
        unsigned char *ret = p;
-       if (s->hit || s->servername_done == 2)
-               return p;
-       ret+=2;
-       if (s->servername_done == 1)  
-               s->servername_done = 2;
 
+       ret+=2;
        if (ret>=limit) return NULL; /* this really never occurs, but ... */
 
-       if (s->session->tlsext_hostname != NULL)
+       if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
                { 
                if (limit - p - 4 < 0) return NULL; 
 
                s2n(TLSEXT_TYPE_server_name,ret);
                s2n(0,ret);
                }
+#ifndef OPENSSL_NO_EC
+       if (s->tlsext_ecpointformatlist != NULL)
+               {
+               /* Add TLS extension ECPointFormats to the ServerHello message */
+               long lenmax; 
+
+               if ((lenmax = limit - p - 5) < 0) return NULL; 
+               if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
+               if (s->tlsext_ecpointformatlist_length > 255)
+                       {
+                       SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+                       return NULL;
+                       }
+               
+               s2n(TLSEXT_TYPE_ec_point_formats,ret);
+               s2n(s->tlsext_ecpointformatlist_length + 1,ret);
+               *(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
+               memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
+               ret+=s->tlsext_ecpointformatlist_length;
+               }
+       /* Currently the server should not respond with a SupportedCurves extension */
+#endif /* OPENSSL_NO_EC */
        
        if ((extdatalen = ret-p-2)== 0) 
                return p;
@@ -222,6 +281,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
        unsigned short size;
        unsigned short len;
        unsigned char *data = *p;
+#if 0
+       fprintf(stderr,"ssl_parse_clienthello_tlsext %s\n",s->session->tlsext_hostname?s->session->tlsext_hostname:"NULL");
+#endif
+       s->servername_done = 0;
 
        if (data >= (d+n-2))
                return 1;
@@ -238,6 +301,29 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                if (data+size > (d+n))
                        return 1;
                
+/* The servername extension is treated as follows:
+
+   - Only the hostname type is supported with a maximum length of 255.
+   - The servername is rejected if too long or if it contains zeros,
+     in which case an fatal alert is generated.
+   - The servername field is maintained together with the session cache.
+   - When a session is resumed, the servername call back invoked in order
+     to allow the application to position itself to the right context. 
+   - The servername is acknowledged if it is new for a session or when 
+     it is identical to a previously used for the same session. 
+     Applications can control the behaviour.  They can at any time
+     set a 'desirable' servername for a new SSL object. This can be the
+     case for example with HTTPS when a Host: header field is received and
+     a renegotiation is requested. In this case, a possible servername
+     presented in the new client hello is only acknowledged if it matches
+     the value of the Host: field. 
+   - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+     if they provide for changing an explicit servername context for the session,
+     i.e. when the session has been established with a servername extension. 
+   - On session reconnect, the servername extension may be absent. 
+
+*/      
+
                if (type == TLSEXT_TYPE_server_name)
                        {
                        unsigned char *sdata = data;
@@ -259,16 +345,29 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                case TLSEXT_NAMETYPE_host_name:
                                         if (s->session->tlsext_hostname == NULL)
                                                {
-                                               if (len > 255 || 
+                                               if (len > TLSEXT_MAXLEN_host_name || 
                                                        ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL))
                                                        {
                                                        *al = TLS1_AD_UNRECOGNIZED_NAME;
                                                        return 0;
                                                        }
-                                               
                                                memcpy(s->session->tlsext_hostname, sdata, len);
-                                               s->session->tlsext_hostname[len]='\0'; 
+                                               s->session->tlsext_hostname[len]='\0';
+                                               if (strlen(s->session->tlsext_hostname) != len) {
+                                                       OPENSSL_free(s->session->tlsext_hostname);
+                                                       *al = TLS1_AD_UNRECOGNIZED_NAME;
+                                                       return 0;
+                                               }
+                                               s->servername_done = 1; 
+
+#if 0
+                                               fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_hostname %s\n",s->session->tlsext_hostname);
+#endif
                                                }
+                                       else 
+                                               s->servername_done = strlen(s->session->tlsext_hostname) == len 
+                                                       && strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;
+                                       
                                        break;
 
                                default:
@@ -278,6 +377,63 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                }
                        }
 
+#ifndef OPENSSL_NO_EC
+               else if (type == TLSEXT_TYPE_ec_point_formats)
+                       {
+                       unsigned char *sdata = data;
+                       int ecpointformatlist_length = *(sdata++);
+
+                       if (ecpointformatlist_length != size - 1)
+                               {
+                               *al = TLS1_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       s->session->tlsext_ecpointformatlist_length = 0;
+                       if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
+                       if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+                               {
+                               *al = TLS1_AD_INTERNAL_ERROR;
+                               return 0;
+                               }
+                       s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+                       memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
+#if 0
+                       fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ecpointformatlist (length=%i) ", s->session->tlsext_ecpointformatlist_length);
+                       sdata = s->session->tlsext_ecpointformatlist;
+                       for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
+                               fprintf(stderr,"%i ",*(sdata++));
+                       fprintf(stderr,"\n");
+#endif
+                       }
+               else if (type == TLSEXT_TYPE_elliptic_curves)
+                       {
+                       unsigned char *sdata = data;
+                       int ellipticcurvelist_length = (*(sdata++) << 8);
+                       ellipticcurvelist_length += (*(sdata++));
+
+                       if (ellipticcurvelist_length != size - 2)
+                               {
+                               *al = TLS1_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       s->session->tlsext_ellipticcurvelist_length = 0;
+                       if (s->session->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->session->tlsext_ellipticcurvelist);
+                       if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL)
+                               {
+                               *al = TLS1_AD_INTERNAL_ERROR;
+                               return 0;
+                               }
+                       s->session->tlsext_ellipticcurvelist_length = ellipticcurvelist_length;
+                       memcpy(s->session->tlsext_ellipticcurvelist, sdata, ellipticcurvelist_length);
+#if 0
+                       fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ellipticcurvelist (length=%i) ", s->session->tlsext_ellipticcurvelist_length);
+                       sdata = s->session->tlsext_ellipticcurvelist;
+                       for (i = 0; i < s->session->tlsext_ellipticcurvelist_length; i++)
+                               fprintf(stderr,"%i ",*(sdata++));
+                       fprintf(stderr,"\n");
+#endif
+                       }
+#endif /* OPENSSL_NO_EC */
                data+=size;             
                }
 
@@ -317,6 +473,35 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                        tlsext_servername = 1;   
                        }
 
+#ifndef OPENSSL_NO_EC
+               else if (type == TLSEXT_TYPE_ec_point_formats)
+                       {
+                       unsigned char *sdata = data;
+                       int ecpointformatlist_length = *(sdata++);
+
+                       if (ecpointformatlist_length != size - 1)
+                               {
+                               *al = TLS1_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       s->session->tlsext_ecpointformatlist_length = 0;
+                       if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
+                       if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+                               {
+                               *al = TLS1_AD_INTERNAL_ERROR;
+                               return 0;
+                               }
+                       s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+                       memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
+#if 0
+                       fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
+                       sdata = s->session->tlsext_ecpointformatlist;
+                       for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
+                               fprintf(stderr,"%i ",*(sdata++));
+                       fprintf(stderr,"\n");
+#endif
+                       }
+#endif /* OPENSSL_NO_EC */
                data+=size;             
                }
 
@@ -351,20 +536,278 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
        return 1;
 }
 
-int ssl_check_tlsext(SSL *s,int *al)
+int ssl_prepare_clienthello_tlsext(SSL *s)
        {
-       int ret;
+#ifndef OPENSSL_NO_EC
+       /* If we are client and using an elliptic curve cryptography cipher suite, send the point formats 
+        * and elliptic curves we support.
+        */
+       int using_ecc = 0;
+       int i;
+       unsigned char *j;
+       int algs;
+       STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
+       for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++)
+               {
+               algs = (sk_SSL_CIPHER_value(cipher_stack, i))->algorithms;
+               if ((algs & SSL_kECDH) || (algs & SSL_kECDHE) || (algs & SSL_aECDSA)) 
+                       {
+                       using_ecc = 1;
+                       break;
+                       }
 
-       *al = SSL_AD_UNRECOGNIZED_NAME;
-       if (s->servername_done == 0 && (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0))
+               }
+       using_ecc = using_ecc && (s->version == TLS1_VERSION);
+       if (using_ecc)
                {
-               ret = s->ctx->tlsext_servername_callback(s, al, s->ctx->tlsext_servername_arg);
-               if (ret <= 0)
-                       return ret;
+               if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
+               if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
+                       {
+                       SSLerr(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
+                       return -1;
+                       }
+               s->tlsext_ecpointformatlist_length = 3;
+               s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
+               s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
+               s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
+               /* we support all named elliptic curves in draft-ietf-tls-ecc-12 */
+               if (s->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->tlsext_ellipticcurvelist);
+               if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(50)) == NULL)
+                       {
+                       SSLerr(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
+                       return -1;
+                       }
+               s->tlsext_ellipticcurvelist_length = 50;
+               for (i = 1, j = s->tlsext_ellipticcurvelist; i <= 25; i++)
+                       {
+                       *(j++) = 0x00;
+                       *(j++) = i;
+                       }
                }
-       if (s->servername_done == 1)    
-               s->servername_done = 2;
-       
+#endif /* OPENSSL_NO_EC */
+       return 1;
+}
+
+int ssl_prepare_serverhello_tlsext(SSL *s)
+       {
+#ifndef OPENSSL_NO_EC
+       /* If we are server and using an ECC cipher suite, send the point formats we support 
+        * if the client sent us an ECPointsFormat extension.  Note that the server is not
+        * supposed to send an EllipticCurves extension.
+        */
+       int algs = s->s3->tmp.new_cipher->algorithms;
+       int using_ecc = (algs & SSL_kECDH) || (algs & SSL_kECDHE) || (algs & SSL_aECDSA);
+       using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
+
+       if (using_ecc)
+               {
+               if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
+               if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
+                       {
+                       SSLerr(SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
+                       return -1;
+                       }
+               s->tlsext_ecpointformatlist_length = 3;
+               s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
+               s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
+               s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
+               }
+#endif /* OPENSSL_NO_EC */
        return 1;
+}
+
+int ssl_check_clienthello_tlsext(SSL *s)
+       {
+       int ret=SSL_TLSEXT_ERR_NOACK;
+       int al = SSL_AD_UNRECOGNIZED_NAME;
+
+#ifndef OPENSSL_NO_EC
+       /* The handling of the ECPointFormats extension is done elsewhere, namely in 
+        * ssl3_choose_cipher in s3_lib.c.
+        */
+       /* The handling of the EllipticCurves extension is done elsewhere, namely in 
+        * ssl3_choose_cipher in s3_lib.c.
+        */
+#endif
+
+       if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
+               ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
+       else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)             
+               ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
+
+       switch (ret) {
+               case SSL_TLSEXT_ERR_ALERT_FATAL:
+                       ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+                       return -1;
+
+               case SSL_TLSEXT_ERR_ALERT_WARNING:
+                       ssl3_send_alert(s,SSL3_AL_WARNING,al);
+                       return 1; 
+                                       
+               case SSL_TLSEXT_ERR_NOACK:
+                       s->servername_done=0;
+                       default:
+               return 1;
        }
+}
+
+int ssl_check_serverhello_tlsext(SSL *s)
+       {
+       int ret=SSL_TLSEXT_ERR_NOACK;
+       int al = SSL_AD_UNRECOGNIZED_NAME;
+
+#ifndef OPENSSL_NO_EC
+       /* If we are client and using an elliptic curve cryptography cipher suite, then server
+        * must return a an EC point formats lists containing uncompressed.
+        */
+       int algs = s->s3->tmp.new_cipher->algorithms;
+       if ((s->tlsext_ecpointformatlist != NULL) && (s->tlsext_ecpointformatlist_length > 0) && 
+           ((algs & SSL_kECDH) || (algs & SSL_kECDHE) || (algs & SSL_aECDSA))) 
+               {
+               /* we are using an ECC cipher */
+               size_t i;
+               unsigned char *list;
+               int found_uncompressed = 0;
+               if ((s->session->tlsext_ecpointformatlist == NULL) || (s->session->tlsext_ecpointformatlist_length == 0))
+                       {
+                       SSLerr(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT,SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+                       return -1;
+                       }
+               list = s->session->tlsext_ecpointformatlist;
+               for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
+                       {
+                       if (*(list++) == TLSEXT_ECPOINTFORMAT_uncompressed)
+                               {
+                               found_uncompressed = 1;
+                               break;
+                               }
+                       }
+               if (!found_uncompressed)
+                       {
+                       SSLerr(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT,SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+                       return -1;
+                       }
+               }
+       ret = SSL_TLSEXT_ERR_OK;
+#endif /* OPENSSL_NO_EC */
+
+       if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
+               ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
+       else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)             
+               ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
+
+       switch (ret) {
+               case SSL_TLSEXT_ERR_ALERT_FATAL:
+                       ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+                       return -1;
+
+               case SSL_TLSEXT_ERR_ALERT_WARNING:
+                       ssl3_send_alert(s,SSL3_AL_WARNING,al);
+                       return 1; 
+                                       
+               case SSL_TLSEXT_ERR_NOACK:
+                       s->servername_done=0;
+                       default:
+               return 1;
+       }
+}
 #endif
+
+#ifndef OPENSSL_NO_EC
+int tls1_ec_curve_id2nid(int curve_id)
+{
+       /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+       static int nid_list[26] =
+       {
+               0,
+               NID_sect163k1, /* sect163k1 (1) */
+               NID_sect163r1, /* sect163r1 (2) */
+               NID_sect163r2, /* sect163r2 (3) */
+               NID_sect193r1, /* sect193r1 (4) */ 
+               NID_sect193r2, /* sect193r2 (5) */ 
+               NID_sect233k1, /* sect233k1 (6) */
+               NID_sect233r1, /* sect233r1 (7) */ 
+               NID_sect239k1, /* sect239k1 (8) */ 
+               NID_sect283k1, /* sect283k1 (9) */
+               NID_sect283r1, /* sect283r1 (10) */ 
+               NID_sect409k1, /* sect409k1 (11) */ 
+               NID_sect409r1, /* sect409r1 (12) */
+               NID_sect571k1, /* sect571k1 (13) */ 
+               NID_sect571r1, /* sect571r1 (14) */ 
+               NID_secp160k1, /* secp160k1 (15) */
+               NID_secp160r1, /* secp160r1 (16) */ 
+               NID_secp160r2, /* secp160r2 (17) */ 
+               NID_secp192k1, /* secp192k1 (18) */
+               NID_X9_62_prime192v1, /* secp192r1 (19) */ 
+               NID_secp224k1, /* secp224k1 (20) */ 
+               NID_secp224r1, /* secp224r1 (21) */
+               NID_secp256k1, /* secp256k1 (22) */ 
+               NID_X9_62_prime256v1, /* secp256r1 (23) */ 
+               NID_secp384r1, /* secp384r1 (24) */
+               NID_secp521r1  /* secp521r1 (25) */     
+       };
+       
+       if ((curve_id < 1) || (curve_id > 25)) return 0;
+
+       return nid_list[curve_id];
+}
+
+int tls1_ec_nid2curve_id(int nid)
+{
+       /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+       switch (nid) {
+       case NID_sect163k1: /* sect163k1 (1) */
+               return 1;
+       case NID_sect163r1: /* sect163r1 (2) */
+               return 2;
+       case NID_sect163r2: /* sect163r2 (3) */
+               return 3;
+       case NID_sect193r1: /* sect193r1 (4) */ 
+               return 4;
+       case NID_sect193r2: /* sect193r2 (5) */ 
+               return 5;
+       case NID_sect233k1: /* sect233k1 (6) */
+               return 6;
+       case NID_sect233r1: /* sect233r1 (7) */ 
+               return 7;
+       case NID_sect239k1: /* sect239k1 (8) */ 
+               return 8;
+       case NID_sect283k1: /* sect283k1 (9) */
+               return 9;
+       case NID_sect283r1: /* sect283r1 (10) */ 
+               return 10;
+       case NID_sect409k1: /* sect409k1 (11) */ 
+               return 11;
+       case NID_sect409r1: /* sect409r1 (12) */
+               return 12;
+       case NID_sect571k1: /* sect571k1 (13) */ 
+               return 13;
+       case NID_sect571r1: /* sect571r1 (14) */ 
+               return 14;
+       case NID_secp160k1: /* secp160k1 (15) */
+               return 15;
+       case NID_secp160r1: /* secp160r1 (16) */ 
+               return 16;
+       case NID_secp160r2: /* secp160r2 (17) */ 
+               return 17;
+       case NID_secp192k1: /* secp192k1 (18) */
+               return 18;
+       case NID_X9_62_prime192v1: /* secp192r1 (19) */ 
+               return 19;
+       case NID_secp224k1: /* secp224k1 (20) */ 
+               return 20;
+       case NID_secp224r1: /* secp224r1 (21) */
+               return 21;
+       case NID_secp256k1: /* secp256k1 (22) */ 
+               return 22;
+       case NID_X9_62_prime256v1: /* secp256r1 (23) */ 
+               return 23;
+       case NID_secp384r1: /* secp384r1 (24) */
+               return 24;
+       case NID_secp521r1:  /* secp521r1 (25) */       
+               return 25;
+       default:
+               return 0;
+       }
+}
+#endif /* OPENSSL_NO_EC */