1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/base/asn1_util.h" 6 7 namespace net { 8 9 namespace asn1 { 10 11 bool ParseElement(base::StringPiece* in, 12 unsigned tag_value, 13 base::StringPiece* out, 14 unsigned *out_header_len) { 15 const uint8* data = reinterpret_cast<const uint8*>(in->data()); 16 17 if (in->size() < 2) 18 return false; 19 20 if (static_cast<unsigned char>(data[0]) != tag_value) 21 return false; 22 23 size_t len = 0; 24 if ((data[1] & 0x80) == 0) { 25 // short form length 26 if (out_header_len) 27 *out_header_len = 2; 28 len = static_cast<size_t>(data[1]) + 2; 29 } else { 30 // long form length 31 const unsigned num_bytes = data[1] & 0x7f; 32 if (num_bytes == 0 || num_bytes > 2) 33 return false; 34 if (in->size() < 2 + num_bytes) 35 return false; 36 len = data[2]; 37 if (num_bytes == 2) { 38 if (len == 0) { 39 // the length encoding must be minimal. 40 return false; 41 } 42 len <<= 8; 43 len += data[3]; 44 } 45 if (len < 128) { 46 // the length should have been encoded in short form. This distinguishes 47 // DER from BER encoding. 48 return false; 49 } 50 if (out_header_len) 51 *out_header_len = 2 + num_bytes; 52 len += 2 + num_bytes; 53 } 54 55 if (in->size() < len) 56 return false; 57 if (out) 58 *out = base::StringPiece(in->data(), len); 59 in->remove_prefix(len); 60 return true; 61 } 62 63 bool GetElement(base::StringPiece* in, 64 unsigned tag_value, 65 base::StringPiece* out) { 66 unsigned header_len; 67 if (!ParseElement(in, tag_value, out, &header_len)) 68 return false; 69 if (out) 70 out->remove_prefix(header_len); 71 return true; 72 } 73 74 bool ExtractSPKIFromDERCert(base::StringPiece cert, 75 base::StringPiece* spki_out) { 76 // From RFC 5280, section 4.1 77 // Certificate ::= SEQUENCE { 78 // tbsCertificate TBSCertificate, 79 // signatureAlgorithm AlgorithmIdentifier, 80 // signatureValue BIT STRING } 81 82 // TBSCertificate ::= SEQUENCE { 83 // version [0] EXPLICIT Version DEFAULT v1, 84 // serialNumber CertificateSerialNumber, 85 // signature AlgorithmIdentifier, 86 // issuer Name, 87 // validity Validity, 88 // subject Name, 89 // subjectPublicKeyInfo SubjectPublicKeyInfo, 90 91 base::StringPiece certificate; 92 if (!asn1::GetElement(&cert, asn1::kSEQUENCE, &certificate)) 93 return false; 94 95 base::StringPiece tbs_certificate; 96 if (!asn1::GetElement(&certificate, asn1::kSEQUENCE, &tbs_certificate)) 97 return false; 98 99 // The version is optional, so a failure to parse it is fine. 100 asn1::GetElement(&tbs_certificate, 101 asn1::kCompound | asn1::kContextSpecific | 0, 102 NULL); 103 104 // serialNumber 105 if (!asn1::GetElement(&tbs_certificate, asn1::kINTEGER, NULL)) 106 return false; 107 // signature 108 if (!asn1::GetElement(&tbs_certificate, asn1::kSEQUENCE, NULL)) 109 return false; 110 // issuer 111 if (!asn1::GetElement(&tbs_certificate, asn1::kSEQUENCE, NULL)) 112 return false; 113 // validity 114 if (!asn1::GetElement(&tbs_certificate, asn1::kSEQUENCE, NULL)) 115 return false; 116 // subject 117 if (!asn1::GetElement(&tbs_certificate, asn1::kSEQUENCE, NULL)) 118 return false; 119 // subjectPublicKeyInfo 120 if (!asn1::ParseElement(&tbs_certificate, asn1::kSEQUENCE, spki_out, NULL)) 121 return false; 122 return true; 123 } 124 125 } // namespace asn1 126 127 } // namespace net 128