1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2013 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #define _GNU_SOURCE /* needed for asprintf */
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
20*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
21*288bf522SAndroid Build Coastguard Worker #include <string.h>
22*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
23*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
24*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker #include <crypto_utils/android_pubkey.h>
27*288bf522SAndroid Build Coastguard Worker
28*288bf522SAndroid Build Coastguard Worker #include <openssl/evp.h>
29*288bf522SAndroid Build Coastguard Worker #include <openssl/objects.h>
30*288bf522SAndroid Build Coastguard Worker #include <openssl/pem.h>
31*288bf522SAndroid Build Coastguard Worker #include <openssl/rsa.h>
32*288bf522SAndroid Build Coastguard Worker #include <openssl/sha.h>
33*288bf522SAndroid Build Coastguard Worker
write_public_keyfile(RSA * private_key,const char * private_key_path)34*288bf522SAndroid Build Coastguard Worker static int write_public_keyfile(RSA *private_key, const char *private_key_path)
35*288bf522SAndroid Build Coastguard Worker {
36*288bf522SAndroid Build Coastguard Worker uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE];
37*288bf522SAndroid Build Coastguard Worker BIO *bfile = NULL;
38*288bf522SAndroid Build Coastguard Worker char *path = NULL;
39*288bf522SAndroid Build Coastguard Worker int ret = -1;
40*288bf522SAndroid Build Coastguard Worker
41*288bf522SAndroid Build Coastguard Worker if (asprintf(&path, "%s.pub", private_key_path) < 0)
42*288bf522SAndroid Build Coastguard Worker goto out;
43*288bf522SAndroid Build Coastguard Worker
44*288bf522SAndroid Build Coastguard Worker if (!android_pubkey_encode(private_key, key_data, sizeof(key_data)))
45*288bf522SAndroid Build Coastguard Worker goto out;
46*288bf522SAndroid Build Coastguard Worker
47*288bf522SAndroid Build Coastguard Worker bfile = BIO_new_file(path, "w");
48*288bf522SAndroid Build Coastguard Worker if (!bfile)
49*288bf522SAndroid Build Coastguard Worker goto out;
50*288bf522SAndroid Build Coastguard Worker
51*288bf522SAndroid Build Coastguard Worker BIO_write(bfile, key_data, sizeof(key_data));
52*288bf522SAndroid Build Coastguard Worker BIO_flush(bfile);
53*288bf522SAndroid Build Coastguard Worker
54*288bf522SAndroid Build Coastguard Worker ret = 0;
55*288bf522SAndroid Build Coastguard Worker out:
56*288bf522SAndroid Build Coastguard Worker BIO_free_all(bfile);
57*288bf522SAndroid Build Coastguard Worker free(path);
58*288bf522SAndroid Build Coastguard Worker return ret;
59*288bf522SAndroid Build Coastguard Worker }
60*288bf522SAndroid Build Coastguard Worker
convert_x509(const char * pem_file,const char * key_file)61*288bf522SAndroid Build Coastguard Worker static int convert_x509(const char *pem_file, const char *key_file)
62*288bf522SAndroid Build Coastguard Worker {
63*288bf522SAndroid Build Coastguard Worker int ret = -1;
64*288bf522SAndroid Build Coastguard Worker FILE *f = NULL;
65*288bf522SAndroid Build Coastguard Worker EVP_PKEY *pkey = NULL;
66*288bf522SAndroid Build Coastguard Worker RSA *rsa = NULL;
67*288bf522SAndroid Build Coastguard Worker X509 *cert = NULL;
68*288bf522SAndroid Build Coastguard Worker
69*288bf522SAndroid Build Coastguard Worker if (!pem_file || !key_file) {
70*288bf522SAndroid Build Coastguard Worker goto out;
71*288bf522SAndroid Build Coastguard Worker }
72*288bf522SAndroid Build Coastguard Worker
73*288bf522SAndroid Build Coastguard Worker f = fopen(pem_file, "r");
74*288bf522SAndroid Build Coastguard Worker if (!f) {
75*288bf522SAndroid Build Coastguard Worker printf("Failed to open '%s'\n", pem_file);
76*288bf522SAndroid Build Coastguard Worker goto out;
77*288bf522SAndroid Build Coastguard Worker }
78*288bf522SAndroid Build Coastguard Worker
79*288bf522SAndroid Build Coastguard Worker cert = PEM_read_X509(f, &cert, NULL, NULL);
80*288bf522SAndroid Build Coastguard Worker if (!cert) {
81*288bf522SAndroid Build Coastguard Worker printf("Failed to read PEM certificate from file '%s'\n", pem_file);
82*288bf522SAndroid Build Coastguard Worker goto out;
83*288bf522SAndroid Build Coastguard Worker }
84*288bf522SAndroid Build Coastguard Worker
85*288bf522SAndroid Build Coastguard Worker pkey = X509_get_pubkey(cert);
86*288bf522SAndroid Build Coastguard Worker if (!pkey) {
87*288bf522SAndroid Build Coastguard Worker printf("Failed to extract public key from certificate '%s'\n", pem_file);
88*288bf522SAndroid Build Coastguard Worker goto out;
89*288bf522SAndroid Build Coastguard Worker }
90*288bf522SAndroid Build Coastguard Worker
91*288bf522SAndroid Build Coastguard Worker rsa = EVP_PKEY_get1_RSA(pkey);
92*288bf522SAndroid Build Coastguard Worker if (!rsa) {
93*288bf522SAndroid Build Coastguard Worker printf("Failed to get the RSA public key from '%s'\n", pem_file);
94*288bf522SAndroid Build Coastguard Worker goto out;
95*288bf522SAndroid Build Coastguard Worker }
96*288bf522SAndroid Build Coastguard Worker
97*288bf522SAndroid Build Coastguard Worker if (write_public_keyfile(rsa, key_file) < 0) {
98*288bf522SAndroid Build Coastguard Worker printf("Failed to write public key\n");
99*288bf522SAndroid Build Coastguard Worker goto out;
100*288bf522SAndroid Build Coastguard Worker }
101*288bf522SAndroid Build Coastguard Worker
102*288bf522SAndroid Build Coastguard Worker ret = 0;
103*288bf522SAndroid Build Coastguard Worker
104*288bf522SAndroid Build Coastguard Worker out:
105*288bf522SAndroid Build Coastguard Worker if (f) {
106*288bf522SAndroid Build Coastguard Worker fclose(f);
107*288bf522SAndroid Build Coastguard Worker }
108*288bf522SAndroid Build Coastguard Worker if (cert) {
109*288bf522SAndroid Build Coastguard Worker X509_free(cert);
110*288bf522SAndroid Build Coastguard Worker }
111*288bf522SAndroid Build Coastguard Worker if (pkey) {
112*288bf522SAndroid Build Coastguard Worker EVP_PKEY_free(pkey);
113*288bf522SAndroid Build Coastguard Worker }
114*288bf522SAndroid Build Coastguard Worker if (rsa) {
115*288bf522SAndroid Build Coastguard Worker RSA_free(rsa);
116*288bf522SAndroid Build Coastguard Worker }
117*288bf522SAndroid Build Coastguard Worker
118*288bf522SAndroid Build Coastguard Worker return ret;
119*288bf522SAndroid Build Coastguard Worker }
120*288bf522SAndroid Build Coastguard Worker
generate_key(const char * file)121*288bf522SAndroid Build Coastguard Worker static int generate_key(const char *file)
122*288bf522SAndroid Build Coastguard Worker {
123*288bf522SAndroid Build Coastguard Worker int ret = -1;
124*288bf522SAndroid Build Coastguard Worker FILE *f = NULL;
125*288bf522SAndroid Build Coastguard Worker RSA* rsa = RSA_new();
126*288bf522SAndroid Build Coastguard Worker BIGNUM* exponent = BN_new();
127*288bf522SAndroid Build Coastguard Worker EVP_PKEY* pkey = EVP_PKEY_new();
128*288bf522SAndroid Build Coastguard Worker
129*288bf522SAndroid Build Coastguard Worker if (!pkey || !exponent || !rsa) {
130*288bf522SAndroid Build Coastguard Worker printf("Failed to allocate key\n");
131*288bf522SAndroid Build Coastguard Worker goto out;
132*288bf522SAndroid Build Coastguard Worker }
133*288bf522SAndroid Build Coastguard Worker
134*288bf522SAndroid Build Coastguard Worker BN_set_word(exponent, RSA_F4);
135*288bf522SAndroid Build Coastguard Worker RSA_generate_key_ex(rsa, 2048, exponent, NULL);
136*288bf522SAndroid Build Coastguard Worker EVP_PKEY_set1_RSA(pkey, rsa);
137*288bf522SAndroid Build Coastguard Worker
138*288bf522SAndroid Build Coastguard Worker f = fopen(file, "w");
139*288bf522SAndroid Build Coastguard Worker if (!f) {
140*288bf522SAndroid Build Coastguard Worker printf("Failed to open '%s'\n", file);
141*288bf522SAndroid Build Coastguard Worker goto out;
142*288bf522SAndroid Build Coastguard Worker }
143*288bf522SAndroid Build Coastguard Worker
144*288bf522SAndroid Build Coastguard Worker if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
145*288bf522SAndroid Build Coastguard Worker printf("Failed to write key\n");
146*288bf522SAndroid Build Coastguard Worker goto out;
147*288bf522SAndroid Build Coastguard Worker }
148*288bf522SAndroid Build Coastguard Worker
149*288bf522SAndroid Build Coastguard Worker if (write_public_keyfile(rsa, file) < 0) {
150*288bf522SAndroid Build Coastguard Worker printf("Failed to write public key\n");
151*288bf522SAndroid Build Coastguard Worker goto out;
152*288bf522SAndroid Build Coastguard Worker }
153*288bf522SAndroid Build Coastguard Worker
154*288bf522SAndroid Build Coastguard Worker ret = 0;
155*288bf522SAndroid Build Coastguard Worker
156*288bf522SAndroid Build Coastguard Worker out:
157*288bf522SAndroid Build Coastguard Worker if (f)
158*288bf522SAndroid Build Coastguard Worker fclose(f);
159*288bf522SAndroid Build Coastguard Worker EVP_PKEY_free(pkey);
160*288bf522SAndroid Build Coastguard Worker RSA_free(rsa);
161*288bf522SAndroid Build Coastguard Worker BN_free(exponent);
162*288bf522SAndroid Build Coastguard Worker return ret;
163*288bf522SAndroid Build Coastguard Worker }
164*288bf522SAndroid Build Coastguard Worker
usage()165*288bf522SAndroid Build Coastguard Worker static void usage(){
166*288bf522SAndroid Build Coastguard Worker printf("Usage: generate_verity_key <path-to-key> | -convert <path-to-x509-pem> <path-to-key>\n");
167*288bf522SAndroid Build Coastguard Worker }
168*288bf522SAndroid Build Coastguard Worker
main(int argc,char * argv[])169*288bf522SAndroid Build Coastguard Worker int main(int argc, char *argv[]) {
170*288bf522SAndroid Build Coastguard Worker if (argc == 2) {
171*288bf522SAndroid Build Coastguard Worker return generate_key(argv[1]);
172*288bf522SAndroid Build Coastguard Worker } else if (argc == 4 && !strcmp(argv[1], "-convert")) {
173*288bf522SAndroid Build Coastguard Worker return convert_x509(argv[2], argv[3]);
174*288bf522SAndroid Build Coastguard Worker } else {
175*288bf522SAndroid Build Coastguard Worker usage();
176*288bf522SAndroid Build Coastguard Worker exit(-1);
177*288bf522SAndroid Build Coastguard Worker }
178*288bf522SAndroid Build Coastguard Worker }
179