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