Added encoded OID for hash functions (for use with PKCS#1 v1.5 signatures) into the...
[BearSSL] / src / ssl / ssl_hs_client.t0
index 37c554c..cfe5f78 100644 (file)
@@ -115,32 +115,12 @@ make_pms_rsa(br_ssl_client_context *ctx, int prf_id)
 /*
  * OID for hash functions in RSA signatures.
  */
-static const unsigned char HASH_OID_SHA1[] = {
-       0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
-};
-
-static const unsigned char HASH_OID_SHA224[] = {
-       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
-};
-
-static const unsigned char HASH_OID_SHA256[] = {
-       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
-};
-
-static const unsigned char HASH_OID_SHA384[] = {
-       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
-};
-
-static const unsigned char HASH_OID_SHA512[] = {
-       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
-};
-
 static const unsigned char *HASH_OID[] = {
-       HASH_OID_SHA1,
-       HASH_OID_SHA224,
-       HASH_OID_SHA256,
-       HASH_OID_SHA384,
-       HASH_OID_SHA512
+       BR_HASH_OID_SHA1,
+       BR_HASH_OID_SHA224,
+       BR_HASH_OID_SHA256,
+       BR_HASH_OID_SHA384,
+       BR_HASH_OID_SHA512
 };
 
 /*
@@ -230,8 +210,8 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
 {
        int curve;
        unsigned char key[66], point[133];
-       const unsigned char *generator, *order, *point_src;
-       size_t glen, olen, point_len;
+       const unsigned char *order, *point_src;
+       size_t glen, olen, point_len, xoff, xlen;
        unsigned char mask;
 
        if (ecdhe) {
@@ -271,7 +251,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
         * Compute the common ECDH point, whose X coordinate is the
         * pre-master secret.
         */
-       generator = ctx->eng.iec->generator(curve, &glen);
+       ctx->eng.iec->generator(curve, &glen);
        if (glen != point_len) {
                return -BR_ERR_INVALID_ALGORITHM;
        }
@@ -284,12 +264,10 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
        /*
         * The pre-master secret is the X coordinate.
         */
-       br_ssl_engine_compute_master(&ctx->eng, prf_id, point + 1, glen >> 1);
+       xoff = ctx->eng.iec->xoff(curve, &xlen);
+       br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen);
 
-       memcpy(point, generator, glen);
-       if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) {
-               return -BR_ERR_INVALID_ALGORITHM;
-       }
+       ctx->eng.iec->mulgen(point, key, olen, curve);
        memcpy(ctx->eng.pad, point, glen);
        return (int)glen;
 }
@@ -320,12 +298,12 @@ make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id)
        }
        memcpy(point, pk->key.ec.q, point_len);
        if (!(*ctx->client_auth_vtable)->do_keyx(
-               ctx->client_auth_vtable, point, point_len))
+               ctx->client_auth_vtable, point, &point_len))
        {
                return -1;
        }
        br_ssl_engine_compute_master(&ctx->eng,
-               prf_id, point + 1, point_len >> 1);
+               prf_id, point, point_len);
        return 0;
 }
 
@@ -393,10 +371,9 @@ addr-ctx: hash_id
 
 \ Length of Signatures extension.
 : ext-signatures-length ( -- len )
-       supported-hash-functions { x } drop
-       0
-       supports-rsa-sign? if x + then
-       supports-ecdsa? if x + then
+       supported-hash-functions { num } drop 0
+       supports-rsa-sign? if num + then
+       supports-ecdsa? if num + then
        dup if 1 << 6 + then ;
 
 \ Write supported hash functions ( sign -- )
@@ -429,6 +406,21 @@ addr-ctx: hash_id
 : ext-point-format-length ( -- len )
        supported-curves if 6 else 0 then ;
 
+\ Length of ALPN extension.
+cc: ext-ALPN-length ( -- len ) {
+       size_t u, len;
+
+       if (ENG->protocol_names_num == 0) {
+               T0_PUSH(0);
+               T0_RET();
+       }
+       len = 6;
+       for (u = 0; u < ENG->protocol_names_num; u ++) {
+               len += 1 + strlen(ENG->protocol_names[u]);
+       }
+       T0_PUSH(len);
+}
+
 \ Write handshake message: ClientHello
 : write-ClientHello ( -- )
        { ; total-ext-length }
@@ -438,6 +430,7 @@ addr-ctx: hash_id
        ext-reneg-length ext-sni-length + ext-frag-length +
        ext-signatures-length +
        ext-supported-curves-length + ext-point-format-length +
+       ext-ALPN-length +
        >total-ext-length
 
        \ ClientHello type
@@ -522,13 +515,16 @@ addr-ctx: hash_id
                        supports-rsa-sign? if 1 write-hashes then
                then
                \ TODO: add an API to specify preference order for curves.
-               \ Right now we use increasing id order, which makes P-256
-               \ the preferred curve.
+               \ Right now we send Curve25519 first, then other curves in
+               \ increasing ID values (hence P-256 in second).
                ext-supported-curves-length dup if
                        0x000A write16          \ extension type (10)
                        4 - dup write16         \ extension length
                        2- write16              \ list length
                        supported-curves 0
+                       dup 0x20000000 and if
+                               0xDFFFFFFF and 29 write16
+                       then
                        begin dup 32 < while
                                dup2 >> 1 and if dup write16 then
                                1+
@@ -542,6 +538,21 @@ addr-ctx: hash_id
                        0x0002 write16          \ extension length
                        0x0100 write16          \ value: 1 format: uncompressed
                then
+               ext-ALPN-length dup if
+                       0x0010 write16          \ extension type (16)
+                       4 - dup write16         \ extension length
+                       2- write16              \ list length
+                       addr-protocol_names_num get16 0
+                       begin
+                               dup2 > while
+                               dup copy-protocol-name
+                               dup write8 addr-pad swap write-blob
+                               1+
+                       repeat
+                       2drop
+               else
+                       drop
+               then
                ext-padding-amount 0< ifnot
                        0x0015 write16          \ extension value (21)
                        ext-padding-amount
@@ -595,6 +606,24 @@ addr-ctx: hash_id
                then
        then ;
 
+\ Read the ALPN extension from the server. It must contain a single name,
+\ and that name must match one of our names.
+: read-ALPN-from-server ( lim -- lim )
+       \ Extension contents length.
+       read16 open-elt
+       \ Length of list of names.
+       read16 open-elt
+       \ There should be a single name.
+       read8 addr-pad swap dup { len } read-blob
+       close-elt
+       close-elt
+       len test-protocol-name dup 0< if
+               3 flag? if ERR_UNEXPECTED fail then
+               drop
+       else
+               1+ addr-selected_protocol set16
+       then ;
+
 \ Save a value in a 16-bit field, or check it in case of session resumption.
 : check-resume ( val addr resume -- )
        if get16 = ifnot ERR_RESUME_MISMATCH fail then else set16 then ;
@@ -688,6 +717,7 @@ cc: DEBUG-BLOB ( addr len -- ) {
                ext-signatures-length { ok-signatures }
                ext-supported-curves-length { ok-curves }
                ext-point-format-length { ok-points }
+               ext-ALPN-length { ok-ALPN }
                begin dup while
                        read16
                        case
@@ -753,6 +783,15 @@ cc: DEBUG-BLOB ( addr len -- ) {
                                        read-ignore-16
                                endof
 
+                               \ ALPN.
+                               0x0010 of
+                                       ok-ALPN ifnot
+                                               ERR_EXTRA_EXTENSION fail
+                                       then
+                                       0 >ok-ALPN
+                                       read-ALPN-from-server
+                               endof
+
                                ERR_EXTRA_EXTENSION fail
                        endcase
                repeat
@@ -967,7 +1006,7 @@ cc: get-client-chain ( auth_types -- ) {
                \  - There is an explicit list of supported sign+hash.
                \  - The ECDH flags must be adjusted for RSA/ECDSA
                \    support.
-               read-list-sign-algos dup addr-hashes set16
+               read-list-sign-algos dup addr-hashes set32
 
                \ Trim down the list depending on what hash functions
                \ we support (since the hashing itself is done by the SSL
@@ -1102,6 +1141,7 @@ cc: do-client-sign ( -- sig_len ) {
 : do-handshake ( -- )
        0 addr-application_data set8
        22 addr-record_type_out set8
+       0 addr-selected_protocol set16
        multihash-init
 
        write-ClientHello