xref: /aosp_15_r20/system/extras/verity/generate_verity_key.c (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
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