summaryrefslogtreecommitdiff
path: root/networking/tls.c
diff options
context:
space:
mode:
authorIvan Abrea2018-06-24 20:04:57 +0200
committerDenys Vlasenko2018-06-24 20:05:24 +0200
commit5cb4f9081f3f6575da052b03cb227a7a488b0a8b (patch)
tree88b0ea9660493c832abe155e5a36eaa5158f5e14 /networking/tls.c
parent7c43d431173a73617c079b7945b6629daaa7bca0 (diff)
downloadbusybox-5cb4f9081f3f6575da052b03cb227a7a488b0a8b.zip
busybox-5cb4f9081f3f6575da052b03cb227a7a488b0a8b.tar.gz
tls: fix to handle X.509 v1 certificates correctly
The syntax of public key certificates can be found in RFC 5280 section 4.1. The relevant part of the syntax is the following: TBSCertificate ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, serialNumber CertificateSerialNumber, ... remaining fields omitted ... } The version field has a default value of v1. RFC 5280 section 4.1.2.1 says the following: If only basic fields are present, the version SHOULD be 1 (the value is omitted from the certificate as the default value); however, the version MAY be 2 or 3. To help detect if the version field is present or not, the type of the version field has an explicit tag of [0]. Due to this tag, if the version field is present, its encoding will have an identifier octet that is distinct from that of the serialNumber field. ITU-T X.690 specifies how a value of such a type should be encoded with DER. There is a PDF of X.690 freely available from ITU-T. X.690 section 8.1.2 specifies the format of identifier octets which is the first component of every encoded value. Identifier octets encode the tag of a type. Bits 8 and 7 encode the tag class. Bit 6 will be 0 if the encoding is primitive and 1 if the encoding is constructed. Bits 5 to 1 encode the tag number. X.690 section 8.14 specifies what the identifier octet should be for explicitly tagged types. Section 8.14.3 says if implicit tagging is not used, then the encoding shall be constructed. The version field uses explicit tagging and not implicit tagging, so its encoding will be constructed. This means bit 6 of the identifier octet should be 1. X.690 section 8.14 and Annex A provide examples. Note from their examples that the notation for tags could look like [APPLICATION 2] where both the tag class and tag number are given. For this example, the tag class is 1 (application) and the tag number is 2. For notation like [0] where the tag class is omitted and only the tag number is given, the tag class will be context-specific. Putting this all together, the identifier octet for the DER encoding of the version field should have a tag class of 2 (context-specific), bit 6 as 1 (constructed), and a tag number of 0. Signed-off-by: Ivan Abrea <ivan@algosolutions.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/tls.c')
-rw-r--r--networking/tls.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/networking/tls.c b/networking/tls.c
index 99722cf..c8d9e96 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -1082,6 +1082,8 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
* We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey
*/
uint8_t *end = der + len;
+ uint8_t tag_class, pc, tag_number;
+ int version_present;
/* enter "Certificate" item: [der, end) will be only Cert */
der = enter_der_item(der, &end);
@@ -1089,8 +1091,24 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
/* enter "tbsCertificate" item: [der, end) will be only tbsCert */
der = enter_der_item(der, &end);
+ /*
+ * Skip version field only if it is present. For a v1 certificate, the
+ * version field won't be present since v1 is the default value for the
+ * version field and fields with default values should be omitted (see
+ * RFC 5280 sections 4.1 and 4.1.2.1). If the version field is present
+ * it will have a tag class of 2 (context-specific), bit 6 as 1
+ * (constructed), and a tag number of 0 (see ITU-T X.690 sections 8.1.2
+ * and 8.14).
+ */
+ tag_class = der[0] >> 6; /* bits 8-7 */
+ pc = (der[0] & 32) >> 5; /* bit 6 */
+ tag_number = der[0] & 31; /* bits 5-1 */
+ version_present = tag_class == 2 && pc == 1 && tag_number == 0;
+ if (version_present) {
+ der = skip_der_item(der, end); /* version */
+ }
+
/* skip up to subjectPublicKeyInfo */
- der = skip_der_item(der, end); /* version */
der = skip_der_item(der, end); /* serialNumber */
der = skip_der_item(der, end); /* signatureAlgo */
der = skip_der_item(der, end); /* issuer */