|
@@ -41,6 +41,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
41
|
41
|
#include <ipxe/xfer.h>
|
42
|
42
|
#include <ipxe/open.h>
|
43
|
43
|
#include <ipxe/x509.h>
|
|
44
|
+#include <ipxe/clientcert.h>
|
44
|
45
|
#include <ipxe/rbg.h>
|
45
|
46
|
#include <ipxe/tls.h>
|
46
|
47
|
|
|
@@ -75,8 +76,25 @@ static void tls_clear_cipher ( struct tls_session *tls,
|
75
|
76
|
* TLS uses 24-bit integers in several places, which are awkward to
|
76
|
77
|
* parse in C.
|
77
|
78
|
*/
|
78
|
|
-static unsigned long tls_uint24 ( const uint8_t field24[3] ) {
|
79
|
|
- return ( ( field24[0] << 16 ) + ( field24[1] << 8 ) + field24[2] );
|
|
79
|
+static inline __attribute__ (( always_inline )) unsigned long
|
|
80
|
+tls_uint24 ( const uint8_t field24[3] ) {
|
|
81
|
+ const uint32_t *field32 __attribute__ (( may_alias )) =
|
|
82
|
+ ( ( const void * ) field24 );
|
|
83
|
+ return ( be32_to_cpu ( *field32 ) >> 8 );
|
|
84
|
+}
|
|
85
|
+
|
|
86
|
+/**
|
|
87
|
+ * Set 24-bit field value
|
|
88
|
+ *
|
|
89
|
+ * @v field24 24-bit field
|
|
90
|
+ * @v value Field value
|
|
91
|
+ *
|
|
92
|
+ * The field must be pre-zeroed.
|
|
93
|
+ */
|
|
94
|
+static void tls_set_uint24 ( uint8_t field24[3], unsigned long value ) {
|
|
95
|
+ uint32_t *field32 __attribute__ (( may_alias )) =
|
|
96
|
+ ( ( void * ) field24 );
|
|
97
|
+ *field32 |= cpu_to_be32 ( value << 8 );
|
80
|
98
|
}
|
81
|
99
|
|
82
|
100
|
/******************************************************************************
|
|
@@ -137,6 +155,13 @@ static struct digest_algorithm md5_sha1_algorithm = {
|
137
|
155
|
.final = md5_sha1_final,
|
138
|
156
|
};
|
139
|
157
|
|
|
158
|
+/** RSA digestInfo prefix for MD5+SHA1 algorithm */
|
|
159
|
+struct rsa_digestinfo_prefix rsa_md5_sha1_prefix __rsa_digestinfo_prefix = {
|
|
160
|
+ .digest = &md5_sha1_algorithm,
|
|
161
|
+ .data = NULL, /* MD5+SHA1 signatures have no digestInfo */
|
|
162
|
+ .len = 0,
|
|
163
|
+};
|
|
164
|
+
|
140
|
165
|
/******************************************************************************
|
141
|
166
|
*
|
142
|
167
|
* Cleanup functions
|
|
@@ -674,6 +699,59 @@ static int tls_change_cipher ( struct tls_session *tls,
|
674
|
699
|
return 0;
|
675
|
700
|
}
|
676
|
701
|
|
|
702
|
+/******************************************************************************
|
|
703
|
+ *
|
|
704
|
+ * Signature and hash algorithms
|
|
705
|
+ *
|
|
706
|
+ ******************************************************************************
|
|
707
|
+ */
|
|
708
|
+
|
|
709
|
+/** Supported signature and hash algorithms
|
|
710
|
+ *
|
|
711
|
+ * Note that the default (TLSv1.1 and earlier) algorithm using
|
|
712
|
+ * MD5+SHA1 is never explicitly specified.
|
|
713
|
+ */
|
|
714
|
+struct tls_signature_hash_algorithm tls_signature_hash_algorithms[] = {
|
|
715
|
+ {
|
|
716
|
+ .code = {
|
|
717
|
+ .signature = TLS_RSA_ALGORITHM,
|
|
718
|
+ .hash = TLS_SHA256_ALGORITHM,
|
|
719
|
+ },
|
|
720
|
+ .pubkey = &rsa_algorithm,
|
|
721
|
+ .digest = &sha256_algorithm,
|
|
722
|
+ },
|
|
723
|
+};
|
|
724
|
+
|
|
725
|
+/** Number of supported signature and hash algorithms */
|
|
726
|
+#define TLS_NUM_SIG_HASH_ALGORITHMS \
|
|
727
|
+ ( sizeof ( tls_signature_hash_algorithms ) / \
|
|
728
|
+ sizeof ( tls_signature_hash_algorithms[0] ) )
|
|
729
|
+
|
|
730
|
+/**
|
|
731
|
+ * Find TLS signature and hash algorithm
|
|
732
|
+ *
|
|
733
|
+ * @v pubkey Public-key algorithm
|
|
734
|
+ * @v digest Digest algorithm
|
|
735
|
+ * @ret sig_hash Signature and hash algorithm, or NULL
|
|
736
|
+ */
|
|
737
|
+static struct tls_signature_hash_algorithm *
|
|
738
|
+tls_signature_hash_algorithm ( struct pubkey_algorithm *pubkey,
|
|
739
|
+ struct digest_algorithm *digest ) {
|
|
740
|
+ struct tls_signature_hash_algorithm *sig_hash;
|
|
741
|
+ unsigned int i;
|
|
742
|
+
|
|
743
|
+ /* Identify signature and hash algorithm */
|
|
744
|
+ for ( i = 0 ; i < TLS_NUM_SIG_HASH_ALGORITHMS ; i++ ) {
|
|
745
|
+ sig_hash = &tls_signature_hash_algorithms[i];
|
|
746
|
+ if ( ( sig_hash->pubkey == pubkey ) &&
|
|
747
|
+ ( sig_hash->digest == digest ) ) {
|
|
748
|
+ return sig_hash;
|
|
749
|
+ }
|
|
750
|
+ }
|
|
751
|
+
|
|
752
|
+ return NULL;
|
|
753
|
+}
|
|
754
|
+
|
677
|
755
|
/******************************************************************************
|
678
|
756
|
*
|
679
|
757
|
* Handshake verification
|
|
@@ -812,19 +890,68 @@ static int tls_send_client_hello ( struct tls_session *tls ) {
|
812
|
890
|
* @ret rc Return status code
|
813
|
891
|
*/
|
814
|
892
|
static int tls_send_certificate ( struct tls_session *tls ) {
|
|
893
|
+ int num_certificates = ( have_client_certificate() ? 1 : 0 );
|
815
|
894
|
struct {
|
816
|
895
|
uint32_t type_length;
|
817
|
896
|
uint8_t length[3];
|
818
|
|
- } __attribute__ (( packed )) certificate;
|
|
897
|
+ struct {
|
|
898
|
+ uint8_t length[3];
|
|
899
|
+ uint8_t data[ client_certificate.len ];
|
|
900
|
+ } __attribute__ (( packed )) certificates[num_certificates];
|
|
901
|
+ } __attribute__ (( packed )) *certificate;
|
|
902
|
+ struct x509_certificate cert;
|
|
903
|
+ int rc;
|
819
|
904
|
|
820
|
|
- memset ( &certificate, 0, sizeof ( certificate ) );
|
821
|
|
- certificate.type_length = ( cpu_to_le32 ( TLS_CERTIFICATE ) |
|
822
|
|
- htonl ( sizeof ( certificate ) -
|
823
|
|
- sizeof ( certificate.type_length)));
|
|
905
|
+ /* If we have a certificate to send, determine the applicable
|
|
906
|
+ * public-key algorithm and schedule transmission of
|
|
907
|
+ * CertificateVerify.
|
|
908
|
+ */
|
|
909
|
+ if ( num_certificates ) {
|
824
|
910
|
|
825
|
|
- return tls_send_handshake ( tls, &certificate, sizeof ( certificate ) );
|
826
|
|
-}
|
|
911
|
+ /* Parse certificate to determine public-key algorithm */
|
|
912
|
+ if ( ( rc = x509_parse ( &cert, client_certificate.data,
|
|
913
|
+ client_certificate.len ) ) != 0 ) {
|
|
914
|
+ DBGC ( tls, "TLS %p could not parse client "
|
|
915
|
+ "certificate: %s\n", tls, strerror ( rc ) );
|
|
916
|
+ return rc;
|
|
917
|
+ }
|
|
918
|
+ tls->verify_pubkey = cert.signature_algorithm->pubkey;
|
|
919
|
+
|
|
920
|
+ /* Schedule CertificateVerify transmission */
|
|
921
|
+ tls->tx_pending |= TLS_TX_CERTIFICATE_VERIFY;
|
|
922
|
+ tls_tx_resume ( tls );
|
|
923
|
+ }
|
827
|
924
|
|
|
925
|
+ /* Allocate storage for Certificate record (which may be too
|
|
926
|
+ * large for the stack).
|
|
927
|
+ */
|
|
928
|
+ certificate = zalloc ( sizeof ( *certificate ) );
|
|
929
|
+ if ( ! certificate )
|
|
930
|
+ return -ENOMEM;
|
|
931
|
+
|
|
932
|
+ /* Populate record */
|
|
933
|
+ certificate->type_length =
|
|
934
|
+ ( cpu_to_le32 ( TLS_CERTIFICATE ) |
|
|
935
|
+ htonl ( sizeof ( *certificate ) -
|
|
936
|
+ sizeof ( certificate->type_length ) ) );
|
|
937
|
+ tls_set_uint24 ( certificate->length,
|
|
938
|
+ sizeof ( certificate->certificates ) );
|
|
939
|
+ if ( num_certificates ) {
|
|
940
|
+ tls_set_uint24 ( certificate->certificates[0].length,
|
|
941
|
+ sizeof ( certificate->certificates[0].data ) );
|
|
942
|
+ memcpy ( certificate->certificates[0].data,
|
|
943
|
+ client_certificate.data,
|
|
944
|
+ sizeof ( certificate->certificates[0].data ) );
|
|
945
|
+ }
|
|
946
|
+
|
|
947
|
+ /* Transmit record */
|
|
948
|
+ rc = tls_send_handshake ( tls, certificate, sizeof ( *certificate ) );
|
|
949
|
+
|
|
950
|
+ /* Free record */
|
|
951
|
+ free ( certificate );
|
|
952
|
+
|
|
953
|
+ return rc;
|
|
954
|
+}
|
828
|
955
|
|
829
|
956
|
/**
|
830
|
957
|
* Transmit Client Key Exchange record
|
|
@@ -866,7 +993,97 @@ static int tls_send_client_key_exchange ( struct tls_session *tls ) {
|
866
|
993
|
htons ( sizeof ( key_xchg.encrypted_pre_master_secret ) -
|
867
|
994
|
unused );
|
868
|
995
|
|
869
|
|
- return tls_send_handshake ( tls, &key_xchg, sizeof ( key_xchg ) );
|
|
996
|
+ return tls_send_handshake ( tls, &key_xchg,
|
|
997
|
+ ( sizeof ( key_xchg ) - unused ) );
|
|
998
|
+}
|
|
999
|
+
|
|
1000
|
+/**
|
|
1001
|
+ * Transmit Certificate Verify record
|
|
1002
|
+ *
|
|
1003
|
+ * @v tls TLS session
|
|
1004
|
+ * @ret rc Return status code
|
|
1005
|
+ */
|
|
1006
|
+static int tls_send_certificate_verify ( struct tls_session *tls ) {
|
|
1007
|
+ struct digest_algorithm *digest = tls->handshake_digest;
|
|
1008
|
+ struct pubkey_algorithm *pubkey = tls->verify_pubkey;
|
|
1009
|
+ uint8_t digest_out[ digest->digestsize ];
|
|
1010
|
+ uint8_t ctx[ pubkey->ctxsize ];
|
|
1011
|
+ struct tls_signature_hash_algorithm *sig_hash = NULL;
|
|
1012
|
+ int rc;
|
|
1013
|
+
|
|
1014
|
+ /* Generate digest to be signed */
|
|
1015
|
+ tls_verify_handshake ( tls, digest_out );
|
|
1016
|
+
|
|
1017
|
+ /* Initialise public-key algorithm */
|
|
1018
|
+ if ( ( rc = pubkey_init ( pubkey, ctx, client_private_key.data,
|
|
1019
|
+ client_private_key.len ) ) != 0 ) {
|
|
1020
|
+ DBGC ( tls, "TLS %p could not initialise %s client private "
|
|
1021
|
+ "key: %s\n", tls, pubkey->name, strerror ( rc ) );
|
|
1022
|
+ goto err_pubkey_init;
|
|
1023
|
+ }
|
|
1024
|
+
|
|
1025
|
+ /* TLSv1.2 and later use explicit algorithm identifiers */
|
|
1026
|
+ if ( tls->version >= TLS_VERSION_TLS_1_2 ) {
|
|
1027
|
+ sig_hash = tls_signature_hash_algorithm ( pubkey, digest );
|
|
1028
|
+ if ( ! sig_hash ) {
|
|
1029
|
+ DBGC ( tls, "TLS %p could not identify (%s,%s) "
|
|
1030
|
+ "signature and hash algorithm\n", tls,
|
|
1031
|
+ pubkey->name, digest->name );
|
|
1032
|
+ rc = -ENOTSUP;
|
|
1033
|
+ goto err_sig_hash;
|
|
1034
|
+ }
|
|
1035
|
+ }
|
|
1036
|
+
|
|
1037
|
+ /* Generate and transmit record */
|
|
1038
|
+ {
|
|
1039
|
+ size_t max_len = pubkey_max_len ( pubkey, ctx );
|
|
1040
|
+ int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 );
|
|
1041
|
+ struct {
|
|
1042
|
+ uint32_t type_length;
|
|
1043
|
+ struct tls_signature_hash_id sig_hash[use_sig_hash];
|
|
1044
|
+ uint16_t signature_len;
|
|
1045
|
+ uint8_t signature[max_len];
|
|
1046
|
+ } __attribute__ (( packed )) certificate_verify;
|
|
1047
|
+ size_t unused;
|
|
1048
|
+ int len;
|
|
1049
|
+
|
|
1050
|
+ /* Sign digest */
|
|
1051
|
+ len = pubkey_sign ( pubkey, ctx, digest, digest_out,
|
|
1052
|
+ certificate_verify.signature );
|
|
1053
|
+ if ( len < 0 ) {
|
|
1054
|
+ rc = len;
|
|
1055
|
+ DBGC ( tls, "TLS %p could not sign %s digest using %s "
|
|
1056
|
+ "client private key: %s\n", tls, digest->name,
|
|
1057
|
+ pubkey->name, strerror ( rc ) );
|
|
1058
|
+ goto err_pubkey_sign;
|
|
1059
|
+ }
|
|
1060
|
+ unused = ( max_len - len );
|
|
1061
|
+
|
|
1062
|
+ /* Construct Certificate Verify record */
|
|
1063
|
+ certificate_verify.type_length =
|
|
1064
|
+ ( cpu_to_le32 ( TLS_CERTIFICATE_VERIFY ) |
|
|
1065
|
+ htonl ( sizeof ( certificate_verify ) -
|
|
1066
|
+ sizeof ( certificate_verify.type_length ) -
|
|
1067
|
+ unused ) );
|
|
1068
|
+ if ( use_sig_hash ) {
|
|
1069
|
+ memcpy ( &certificate_verify.sig_hash[0],
|
|
1070
|
+ &sig_hash->code,
|
|
1071
|
+ sizeof ( certificate_verify.sig_hash[0] ) );
|
|
1072
|
+ }
|
|
1073
|
+ certificate_verify.signature_len =
|
|
1074
|
+ htons ( sizeof ( certificate_verify.signature ) -
|
|
1075
|
+ unused );
|
|
1076
|
+
|
|
1077
|
+ /* Transmit record */
|
|
1078
|
+ rc = tls_send_handshake ( tls, &certificate_verify,
|
|
1079
|
+ ( sizeof ( certificate_verify ) - unused ) );
|
|
1080
|
+ }
|
|
1081
|
+
|
|
1082
|
+ err_pubkey_sign:
|
|
1083
|
+ err_sig_hash:
|
|
1084
|
+ pubkey_final ( pubkey, ctx );
|
|
1085
|
+ err_pubkey_init:
|
|
1086
|
+ return rc;
|
870
|
1087
|
}
|
871
|
1088
|
|
872
|
1089
|
/**
|
|
@@ -1182,9 +1399,8 @@ static int tls_new_certificate_request ( struct tls_session *tls,
|
1182
|
1399
|
const void *data __unused,
|
1183
|
1400
|
size_t len __unused ) {
|
1184
|
1401
|
|
1185
|
|
- /* We can only send an empty certificate (as mandated by
|
1186
|
|
- * TLSv1.2), so there is no point in parsing the Certificate
|
1187
|
|
- * Request.
|
|
1402
|
+ /* We can only send a single certificate, so there is no point
|
|
1403
|
+ * in parsing the Certificate Request.
|
1188
|
1404
|
*/
|
1189
|
1405
|
|
1190
|
1406
|
/* Schedule Certificate transmission */
|
|
@@ -2002,6 +2218,14 @@ static void tls_tx_step ( struct tls_session *tls ) {
|
2002
|
2218
|
goto err;
|
2003
|
2219
|
}
|
2004
|
2220
|
tls->tx_pending &= ~TLS_TX_CLIENT_KEY_EXCHANGE;
|
|
2221
|
+ } else if ( tls->tx_pending & TLS_TX_CERTIFICATE_VERIFY ) {
|
|
2222
|
+ /* Send Certificate Verify */
|
|
2223
|
+ if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) {
|
|
2224
|
+ DBGC ( tls, "TLS %p could not send Certificate "
|
|
2225
|
+ "Verify: %s\n", tls, strerror ( rc ) );
|
|
2226
|
+ goto err;
|
|
2227
|
+ }
|
|
2228
|
+ tls->tx_pending &= ~TLS_TX_CERTIFICATE_VERIFY;
|
2005
|
2229
|
} else if ( tls->tx_pending & TLS_TX_CHANGE_CIPHER ) {
|
2006
|
2230
|
/* Send Change Cipher, and then change the cipher in use */
|
2007
|
2231
|
if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
|