| 93 | |
| 94 | |
| 95 | Try<X509*> generate_x509( |
| 96 | EVP_PKEY* subject_key, |
| 97 | EVP_PKEY* sign_key, |
| 98 | const Option<X509*>& parent_certificate, |
| 99 | int serial, |
| 100 | int days, |
| 101 | Option<string> hostname, |
| 102 | const Option<net::IP>& ip) |
| 103 | { |
| 104 | Option<X509_NAME*> issuer_name = None(); |
| 105 | if (parent_certificate.isNone()) { |
| 106 | // If there is no parent certificate, then the subject and |
| 107 | // signing key must be the same. |
| 108 | if (subject_key != sign_key) { |
| 109 | return Error("Subject vs signing key mismatch"); |
| 110 | } |
| 111 | } else { |
| 112 | // If there is a parent certificate, then set the issuer name to |
| 113 | // be that of the parent. |
| 114 | issuer_name = X509_get_subject_name(parent_certificate.get()); |
| 115 | |
| 116 | if (issuer_name.get() == nullptr) { |
| 117 | return Error("Failed to get subject name of parent certificate: " |
| 118 | "X509_get_subject_name"); |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | // Allocate the in-memory structure for the certificate. |
| 123 | X509* x509 = X509_new(); |
| 124 | if (x509 == nullptr) { |
| 125 | return Error("Failed to allocate certification: X509_new"); |
| 126 | } |
| 127 | |
| 128 | // Set the version to V3. |
| 129 | if (X509_set_version(x509, 2) != 1) { |
| 130 | X509_free(x509); |
| 131 | return Error("Failed to set version: X509_set_version"); |
| 132 | } |
| 133 | |
| 134 | // Set the serial number. |
| 135 | if (ASN1_INTEGER_set(X509_get_serialNumber(x509), serial) != 1) { |
| 136 | X509_free(x509); |
| 137 | return Error("Failed to set serial number: ASN1_INTEGER_set"); |
| 138 | } |
| 139 | |
| 140 | // Make this certificate valid for 'days' number of days from now. |
| 141 | if (X509_gmtime_adj(X509_get_notBefore(x509), 0) == nullptr || |
| 142 | X509_gmtime_adj(X509_get_notAfter(x509), |
| 143 | 60L * 60L * 24L * days) == nullptr) { |
| 144 | X509_free(x509); |
| 145 | return Error("Failed to set valid days of certificate: X509_gmtime_adj"); |
| 146 | } |
| 147 | |
| 148 | // Set the public key for our certificate based on the subject key. |
| 149 | if (X509_set_pubkey(x509, subject_key) != 1) { |
| 150 | X509_free(x509); |
| 151 | return Error("Failed to set public key: X509_set_pubkey"); |
| 152 | } |