Add TLS exporter.
[openssl.git] / ssl / t1_enc.c
index 3452b25c456f0ee33235c3833e2ee6ae8bce6b72..b9d0dd3757c37b127923e1f8d24b3672abba0c3e 100644 (file)
@@ -1119,6 +1119,95 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
        return(SSL3_MASTER_SECRET_SIZE);
        }
 
+int tls1_export_keying_material(SSL *s, unsigned char *out, unsigned int olen, 
+         const char *label, unsigned int llen, const unsigned char *context, 
+         unsigned int contextlen, int use_context)
+       {
+       unsigned char *buff;
+       unsigned char *val;
+       unsigned int vallen, currentvalpos, rv;
+
+#ifdef KSSL_DEBUG
+       printf ("tls1_export_keying_material(%p, %p,%d, %s,%d, %p,%d)\n", s, out,olen, label,llen, p,plen);
+#endif /* KSSL_DEBUG */
+
+       buff = OPENSSL_malloc(olen);
+       if (buff == NULL) goto err2;
+
+       /* construct PRF arguments
+        * we construct the PRF argument ourself rather than passing separate
+        * values into the TLS PRF to ensure that the concatenation of values
+        * does not create a prohibited label.
+        */
+       vallen = llen + SSL3_RANDOM_SIZE * 2;
+        if (use_context) 
+                {
+                vallen +=  2 + contextlen;
+                }
+
+       val = OPENSSL_malloc(vallen);
+       if (val == NULL) goto err2;
+       currentvalpos = 0;
+       memcpy(val + currentvalpos, (unsigned char *) label, llen);
+       currentvalpos += llen;
+       memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
+       currentvalpos += SSL3_RANDOM_SIZE;
+       memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
+       currentvalpos += SSL3_RANDOM_SIZE;
+
+        if (use_context)
+                {
+                val[currentvalpos] = (contextlen << 8) & 0xff;
+                currentvalpos++;
+                val[currentvalpos] = contextlen & 0xff;
+                currentvalpos++;
+                if ((contextlen > 0) || (context != NULL)) 
+                        {
+                        memcpy(val + currentvalpos, context, contextlen);
+                        }
+                }
+
+       /* disallow prohibited labels
+        * note that SSL3_RANDOM_SIZE > max(prohibited label len) =
+        * 15, so size of val > max(prohibited label len) = 15 and the
+        * comparisons won't have buffer overflow
+        */
+       if (bcmp(val, TLS_MD_CLIENT_FINISH_CONST,
+                TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0) goto err1;
+       if (bcmp(val, TLS_MD_SERVER_FINISH_CONST,
+                TLS_MD_SERVER_FINISH_CONST_SIZE) == 0) goto err1;
+       if (bcmp(val, TLS_MD_MASTER_SECRET_CONST,
+                TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) goto err1;
+       if (bcmp(val, TLS_MD_KEY_EXPANSION_CONST,
+                TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) goto err1;
+
+       tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+               val, vallen,
+               NULL, 0,
+               NULL, 0,
+               NULL, 0,
+               NULL, 0,
+               s->session->master_key,s->session->master_key_length,
+               out,buff,olen);
+
+#ifdef KSSL_DEBUG
+       printf ("tls1_export_keying_material() complete\n");
+#endif /* KSSL_DEBUG */
+       rv = olen;
+       goto ret;
+err1:
+       SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+       rv = 0;
+       goto ret;
+err2:
+       SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE);
+       rv = 0;
+ret:
+       if (buff != NULL) OPENSSL_free(buff);
+       if (val != NULL) OPENSSL_free(val);
+       return(rv);
+       }
+
 int tls1_alert_code(int code)
        {
        switch (code)