Updates spec file version
[platform/upstream/crda.git] / reglib.c
1 #include <errno.h>
2 #include <stdio.h>
3 #include <arpa/inet.h>
4 #include "reglib.h"
5
6 #ifdef USE_OPENSSL
7 #include <openssl/objects.h>
8 #include <openssl/rsa.h>
9 #include <openssl/sha.h>
10 #endif
11
12 #ifdef USE_GCRYPT
13 #include <gcrypt.h>
14 #endif
15
16 #include "reglib.h"
17
18 #ifdef USE_OPENSSL
19 #include "keys-ssl.c"
20 #endif
21
22 #ifdef USE_GCRYPT
23 #include "keys-gcrypt.c"
24 #endif
25
26 void *crda_get_file_ptr(__u8 *db, int dblen, int structlen, __be32 ptr)
27 {
28         __u32 p = ntohl(ptr);
29
30         if (p > dblen - structlen) {
31                 fprintf(stderr, "Invalid database file, bad pointer!\n");
32                 exit(3);
33         }
34
35         return (void *)(db + p);
36 }
37
38 /*
39  * Checks the validity of the signature found on the regulatory
40  * database against the array 'keys'. Returns 1 if there exists
41  * at least one key in the array such that the signature is valid
42  * against that key; 0 otherwise.
43  */
44 int crda_verify_db_signature(__u8 *db, int dblen, int siglen)
45 {
46 #ifdef USE_OPENSSL
47         RSA *rsa;
48         __u8 hash[SHA_DIGEST_LENGTH];
49         unsigned int i;
50         int ok = 0;
51
52         rsa = RSA_new();
53         if (!rsa) {
54                 fprintf(stderr, "Failed to create RSA key.\n");
55                 goto out;
56         }
57
58         if (SHA1(db, dblen, hash) != hash) {
59                 fprintf(stderr, "Failed to calculate SHA1 sum.\n");
60                 RSA_free(rsa);
61                 goto out;
62         }
63
64         for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) {
65                 rsa->e = &keys[i].e;
66                 rsa->n = &keys[i].n;
67
68                 if (RSA_size(rsa) != siglen)
69                         continue;
70
71                 ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
72                                 db + dblen, siglen, rsa) == 1;
73         }
74
75         rsa->e = NULL;
76         rsa->n = NULL;
77         RSA_free(rsa);
78 #endif
79
80 #ifdef USE_GCRYPT
81         gcry_mpi_t mpi_e, mpi_n;
82         gcry_sexp_t rsa, signature, data;
83         __u8 hash[20];
84         unsigned int i;
85         int ok = 0;
86
87         /* initialise */
88         gcry_check_version(NULL);
89
90         /* hash the db */
91         gcry_md_hash_buffer(GCRY_MD_SHA1, hash, db, dblen);
92
93         if (gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))",
94                             20, hash)) {
95                 fprintf(stderr, "Failed to build data S-expression.\n");
96                 goto out;
97         }
98
99         if (gcry_sexp_build(&signature, NULL, "(sig-val (rsa (s %b)))",
100                             siglen, db + dblen)) {
101                 fprintf(stderr, "Failed to build signature S-expression.\n");
102                 goto out;
103         }
104
105         for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) {
106                 if (gcry_mpi_scan(&mpi_e, GCRYMPI_FMT_USG,
107                                 keys[i].e, keys[i].len_e, NULL) ||
108                     gcry_mpi_scan(&mpi_n, GCRYMPI_FMT_USG,
109                                 keys[i].n, keys[i].len_n, NULL)) {
110                         fprintf(stderr, "Failed to convert numbers.\n");
111                         goto out;
112                 }
113
114                 if (gcry_sexp_build(&rsa, NULL,
115                                     "(public-key (rsa (n %m) (e %m)))",
116                                     mpi_n, mpi_e)) {
117                         fprintf(stderr, "Failed to build RSA S-expression.\n");
118                         goto out;
119                 }
120
121                 ok = gcry_pk_verify(signature, data, rsa) == 0;
122         }
123 #endif
124
125 #if defined(USE_OPENSSL) || defined(USE_GCRYPT)
126         if (!ok)
127                 fprintf(stderr, "Database signature verification failed.\n");
128
129 out:
130         return ok;
131 #else
132         return 1;
133 #endif
134 }