|
|
1.1 root 1: /*
2: * Copyright (C) 2007 Michael Brown <[email protected]>.
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 <ipxe/asn1.h>
25: #include <ipxe/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.