|
|
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.