1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "adb/crypto/x509_generator.h" 18 19 #include <vector> 20 21 #include <android-base/logging.h> 22 #include <crypto_utils/android_pubkey.h> 23 #include <openssl/bn.h> 24 #include <openssl/pem.h> 25 #include <openssl/rsa.h> 26 27 namespace adb { 28 namespace crypto { 29 30 namespace { 31 32 const char kBasicConstraints[] = "critical,CA:TRUE"; 33 const char kKeyUsage[] = "critical,keyCertSign,cRLSign,digitalSignature"; 34 const char kSubjectKeyIdentifier[] = "hash"; 35 constexpr int kCertLifetimeSeconds = 10 * 365 * 24 * 60 * 60; 36 37 bool add_ext(X509* cert, int nid, const char* value) { 38 size_t len = strlen(value) + 1; 39 std::vector<char> mutableValue(value, value + len); 40 X509V3_CTX context; 41 42 X509V3_set_ctx_nodb(&context); 43 44 X509V3_set_ctx(&context, cert, cert, nullptr, nullptr, 0); 45 X509_EXTENSION* ex = X509V3_EXT_nconf_nid(nullptr, &context, nid, mutableValue.data()); 46 if (!ex) { 47 return false; 48 } 49 50 X509_add_ext(cert, ex, -1); 51 X509_EXTENSION_free(ex); 52 return true; 53 } 54 55 } // namespace 56 57 bssl::UniquePtr<X509> GenerateX509Certificate(EVP_PKEY* pkey) { 58 CHECK(pkey); 59 bssl::UniquePtr<X509> x509(X509_new()); 60 if (!x509) { 61 LOG(ERROR) << "Unable to allocate x509 container"; 62 return nullptr; 63 } 64 X509_set_version(x509.get(), 2); 65 66 ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), 1); 67 X509_gmtime_adj(X509_get_notBefore(x509.get()), 0); 68 X509_gmtime_adj(X509_get_notAfter(x509.get()), kCertLifetimeSeconds); 69 70 if (!X509_set_pubkey(x509.get(), pkey)) { 71 LOG(ERROR) << "Unable to set x509 public key"; 72 return nullptr; 73 } 74 75 X509_NAME* name = X509_get_subject_name(x509.get()); 76 if (!name) { 77 LOG(ERROR) << "Unable to get x509 subject name"; 78 return nullptr; 79 } 80 X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, 81 reinterpret_cast<const unsigned char*>("US"), -1, -1, 0); 82 X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, 83 reinterpret_cast<const unsigned char*>("Android"), -1, -1, 0); 84 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, 85 reinterpret_cast<const unsigned char*>("Adb"), -1, -1, 0); 86 if (!X509_set_issuer_name(x509.get(), name)) { 87 LOG(ERROR) << "Unable to set x509 issuer name"; 88 return nullptr; 89 } 90 91 add_ext(x509.get(), NID_basic_constraints, kBasicConstraints); 92 add_ext(x509.get(), NID_key_usage, kKeyUsage); 93 add_ext(x509.get(), NID_subject_key_identifier, kSubjectKeyIdentifier); 94 95 int bytes = X509_sign(x509.get(), pkey, EVP_sha256()); 96 if (bytes <= 0) { 97 LOG(ERROR) << "Unable to sign x509 certificate"; 98 return nullptr; 99 } 100 101 return x509; 102 } 103 104 std::string X509ToPEMString(X509* x509) { 105 bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem())); 106 int rc = PEM_write_bio_X509(bio.get(), x509); 107 if (rc != 1) { 108 LOG(ERROR) << "PEM_write_bio_X509 failed"; 109 return ""; 110 } 111 112 BUF_MEM* mem = nullptr; 113 BIO_get_mem_ptr(bio.get(), &mem); 114 if (!mem || !mem->data || !mem->length) { 115 LOG(ERROR) << "BIO_get_mem_ptr failed"; 116 return ""; 117 } 118 119 return std::string(mem->data, mem->length); 120 } 121 122 } // namespace crypto 123 } // namespace adb 124