1 /* 2 * Copyright (C) 2007 Michael Brown <mbrown (at) fensystems.co.uk>. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19 FILE_LICENCE ( GPL2_OR_LATER ); 20 21 #include <stdlib.h> 22 #include <string.h> 23 #include <errno.h> 24 #include <gpxe/asn1.h> 25 #include <gpxe/x509.h> 26 27 /** @file 28 * 29 * X.509 certificates 30 * 31 * The structure of X.509v3 certificates is concisely documented in 32 * RFC5280 section 4.1. The structure of RSA public keys is 33 * documented in RFC2313. 34 */ 35 36 /** Object Identifier for "rsaEncryption" (1.2.840.113549.1.1.1) */ 37 static const uint8_t oid_rsa_encryption[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 38 0x0d, 0x01, 0x01, 0x01 }; 39 40 /** 41 * Identify X.509 certificate public key 42 * 43 * @v certificate Certificate 44 * @v algorithm Public key algorithm to fill in 45 * @v pubkey Public key value to fill in 46 * @ret rc Return status code 47 */ 48 static int x509_public_key ( const struct asn1_cursor *certificate, 49 struct asn1_cursor *algorithm, 50 struct asn1_cursor *pubkey ) { 51 struct asn1_cursor cursor; 52 int rc; 53 54 /* Locate subjectPublicKeyInfo */ 55 memcpy ( &cursor, certificate, sizeof ( cursor ) ); 56 rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */ 57 asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */ 58 asn1_skip ( &cursor, ASN1_EXPLICIT_TAG ), /* version */ 59 asn1_skip ( &cursor, ASN1_INTEGER ), /* serialNumber */ 60 asn1_skip ( &cursor, ASN1_SEQUENCE ), /* signature */ 61 asn1_skip ( &cursor, ASN1_SEQUENCE ), /* issuer */ 62 asn1_skip ( &cursor, ASN1_SEQUENCE ), /* validity */ 63 asn1_skip ( &cursor, ASN1_SEQUENCE ), /* name */ 64 asn1_enter ( &cursor, ASN1_SEQUENCE )/* subjectPublicKeyInfo*/); 65 if ( rc != 0 ) { 66 DBG ( "Cannot locate subjectPublicKeyInfo in:\n" ); 67 DBG_HDA ( 0, certificate->data, certificate->len ); 68 return rc; 69 } 70 71 /* Locate algorithm */ 72 memcpy ( algorithm, &cursor, sizeof ( *algorithm ) ); 73 rc = ( asn1_enter ( algorithm, ASN1_SEQUENCE ) /* algorithm */ ); 74 if ( rc != 0 ) { 75 DBG ( "Cannot locate algorithm in:\n" ); 76 DBG_HDA ( 0, certificate->data, certificate->len ); 77 return rc; 78 } 79 80 /* Locate subjectPublicKey */ 81 memcpy ( pubkey, &cursor, sizeof ( *pubkey ) ); 82 rc = ( asn1_skip ( pubkey, ASN1_SEQUENCE ), /* algorithm */ 83 asn1_enter ( pubkey, ASN1_BIT_STRING ) /* subjectPublicKey*/ ); 84 if ( rc != 0 ) { 85 DBG ( "Cannot locate subjectPublicKey in:\n" ); 86 DBG_HDA ( 0, certificate->data, certificate->len ); 87 return rc; 88 } 89 90 return 0; 91 } 92 93 /** 94 * Identify X.509 certificate RSA modulus and public exponent 95 * 96 * @v certificate Certificate 97 * @v rsa RSA public key to fill in 98 * @ret rc Return status code 99 * 100 * The caller is responsible for eventually calling 101 * x509_free_rsa_public_key() to free the storage allocated to hold 102 * the RSA modulus and exponent. 103 */ 104 int x509_rsa_public_key ( const struct asn1_cursor *certificate, 105 struct x509_rsa_public_key *rsa_pubkey ) { 106 struct asn1_cursor algorithm; 107 struct asn1_cursor pubkey; 108 struct asn1_cursor modulus; 109 struct asn1_cursor exponent; 110 int rc; 111 112 /* First, extract the public key algorithm and key data */ 113 if ( ( rc = x509_public_key ( certificate, &algorithm, 114 &pubkey ) ) != 0 ) 115 return rc; 116 117 /* Check that algorithm is RSA */ 118 rc = ( asn1_enter ( &algorithm, ASN1_OID ) /* algorithm */ ); 119 if ( rc != 0 ) { 120 DBG ( "Cannot locate algorithm:\n" ); 121 DBG_HDA ( 0, certificate->data, certificate->len ); 122 return rc; 123 } 124 if ( ( algorithm.len != sizeof ( oid_rsa_encryption ) ) || 125 ( memcmp ( algorithm.data, &oid_rsa_encryption, 126 sizeof ( oid_rsa_encryption ) ) != 0 ) ) { 127 DBG ( "algorithm is not rsaEncryption in:\n" ); 128 DBG_HDA ( 0, certificate->data, certificate->len ); 129 return -ENOTSUP; 130 } 131 132 /* Check that public key is a byte string, i.e. that the 133 * "unused bits" byte contains zero. 134 */ 135 if ( ( pubkey.len < 1 ) || 136 ( ( *( uint8_t * ) pubkey.data ) != 0 ) ) { 137 DBG ( "subjectPublicKey is not a byte string in:\n" ); 138 DBG_HDA ( 0, certificate->data, certificate->len ); 139 return -ENOTSUP; 140 } 141 pubkey.data++; 142 pubkey.len--; 143 144 /* Pick out the modulus and exponent */ 145 rc = ( asn1_enter ( &pubkey, ASN1_SEQUENCE ) /* RSAPublicKey */ ); 146 if ( rc != 0 ) { 147 DBG ( "Cannot locate RSAPublicKey in:\n" ); 148 DBG_HDA ( 0, certificate->data, certificate->len ); 149 return -ENOTSUP; 150 } 151 memcpy ( &modulus, &pubkey, sizeof ( modulus ) ); 152 rc = ( asn1_enter ( &modulus, ASN1_INTEGER ) /* modulus */ ); 153 if ( rc != 0 ) { 154 DBG ( "Cannot locate modulus in:\n" ); 155 DBG_HDA ( 0, certificate->data, certificate->len ); 156 return -ENOTSUP; 157 } 158 memcpy ( &exponent, &pubkey, sizeof ( exponent ) ); 159 rc = ( asn1_skip ( &exponent, ASN1_INTEGER ), /* modulus */ 160 asn1_enter ( &exponent, ASN1_INTEGER ) /* publicExponent */ ); 161 if ( rc != 0 ) { 162 DBG ( "Cannot locate publicExponent in:\n" ); 163 DBG_HDA ( 0, certificate->data, certificate->len ); 164 return -ENOTSUP; 165 } 166 167 /* Allocate space and copy out modulus and exponent */ 168 rsa_pubkey->modulus = malloc ( modulus.len + exponent.len ); 169 if ( ! rsa_pubkey->modulus ) 170 return -ENOMEM; 171 rsa_pubkey->exponent = ( rsa_pubkey->modulus + modulus.len ); 172 memcpy ( rsa_pubkey->modulus, modulus.data, modulus.len ); 173 rsa_pubkey->modulus_len = modulus.len; 174 memcpy ( rsa_pubkey->exponent, exponent.data, exponent.len ); 175 rsa_pubkey->exponent_len = exponent.len; 176 177 DBG2 ( "RSA modulus:\n" ); 178 DBG2_HDA ( 0, rsa_pubkey->modulus, rsa_pubkey->modulus_len ); 179 DBG2 ( "RSA exponent:\n" ); 180 DBG2_HDA ( 0, rsa_pubkey->exponent, rsa_pubkey->exponent_len ); 181 182 return 0; 183 } 184