Commit 61584141 authored by Davide Pesavento's avatar Davide Pesavento Committed by Luis R. Rodriguez

Consolidate db signature validation in one function.

Both crda.c and dump.c had their own version of the code which
checks the validity of the signature on the regulatory db.
Having a common implementation shared by both files makes
maintenance easier and removes code duplication.
Signed-off-by: 's avatarDavide Pesavento <davidepesa@gmail.com>
Signed-off-by: 's avatarLuis R. Rodriguez <lrodriguez@atheros.com>
parent 8cae7f54
......@@ -17,23 +17,23 @@ INSTALL ?= install
CRDA_LIB = "/usr/lib/crda/"
all: regulatory.bin warn crda
all: regulatory.bin warn crda
@$(MAKE) --no-print-directory -f Makefile verify
regulatory.bin: db2bin.py key.priv.pem db.txt dbparse.py
@./db2bin.py regulatory.bin db.txt key.priv.pem
crda: keys-gcrypt.c keys-ssl.c crda.c regdb.h
$(CC) $(CFLAGS) $(LDFLAGS) -lnl -o $@ crda.c
crda: keys-ssl.c keys-gcrypt.c regdb.h regdb.o crda.o
$(CC) $(CFLAGS) $(LDFLAGS) -lnl -o $@ regdb.o crda.o
clean:
@rm -f regulatory.bin dump *~ *.pyc keys-*.c crda
@rm -f regulatory.bin crda dump *.o *~ *.pyc keys-*.c
@if test -f key.priv.pem && diff -qNs test-key key.priv.pem >/dev/null ; then \
rm -f key.priv.pem;\
fi
warn:
@if test ! -f key.priv.pem || diff -qNs test-key key.priv.pem >/dev/null ; then \
@if test ! -f key.priv.pem || diff -qNs test-key key.priv.pem >/dev/null ; then \
echo '**************************************';\
echo '** WARNING! **';\
echo '** No key found, using TEST key! **';\
......@@ -46,8 +46,8 @@ key.priv.pem:
generate_key:
openssl genrsa -out key.priv.pem 2048
dump: dump.c regdb.h keys-ssl.c keys-gcrypt.c
$(CC) $(CFLAGS) $(LDFLAGS) dump.c -o dump
dump: keys-ssl.c keys-gcrypt.c regdb.h regdb.o dump.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ regdb.o dump.o
keys-ssl.c: key2pub.py $(wildcard *.pem)
@./key2pub.py --ssl *.pem > keys-ssl.c
......
......@@ -21,21 +21,6 @@
#include "regdb.h"
#ifdef USE_OPENSSL
#include <openssl/objects.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include "keys-ssl.c"
#endif
#ifdef USE_GCRYPT
#include <gcrypt.h>
#include "keys-gcrypt.c"
#endif
struct nl80211_state {
struct nl_handle *nl_handle;
struct nl_cache *nl_cache;
......@@ -199,18 +184,6 @@ int main(int argc, char **argv)
struct nlattr *nl_reg_rules;
int num_rules;
#ifdef USE_OPENSSL
RSA *rsa;
__u8 hash[SHA_DIGEST_LENGTH];
int ok = 0;
#endif
#ifdef USE_GCRYPT
gcry_mpi_t mpi_e, mpi_n;
gcry_sexp_t rsa, signature, data;
__u8 hash[20];
int ok = 0;
#endif
const char regdb[] = "/usr/lib/crda/regulatory.bin";
if (argc != 1) {
......@@ -274,90 +247,8 @@ int main(int argc, char **argv)
}
/* verify signature */
#ifdef USE_OPENSSL
rsa = RSA_new();
if (!rsa) {
fprintf(stderr, "Failed to create RSA key\n");
return -EINVAL;
}
if (SHA1(db, dblen, hash) != hash) {
fprintf(stderr, "Failed to calculate SHA sum\n");
RSA_free(rsa);
return -EINVAL;
}
for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
rsa->e = &keys[i].e;
rsa->n = &keys[i].n;
if (RSA_size(rsa) != siglen)
continue;
ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
db + dblen, siglen, rsa) == 1;
if (ok)
break;
}
rsa->e = NULL;
rsa->n = NULL;
RSA_free(rsa);
if (!ok) {
fprintf(stderr, "Database signature wrong\n");
if (!crda_verify_db_signature(db, dblen, siglen))
return -EINVAL;
}
BN_print_fp(stdout, &keys[0].n);
#endif
#ifdef USE_GCRYPT
/* initialise */
gcry_check_version(NULL);
/* hash the db */
gcry_md_hash_buffer(GCRY_MD_SHA1, hash, db, dblen);
if (gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))",
20, hash)) {
fprintf(stderr, "failed to build data expression\n");
return 2;
}
if (gcry_sexp_build(&signature, NULL, "(sig-val (rsa (s %b)))",
siglen, db + dblen)) {
fprintf(stderr, "failed to build signature expression\n");
return 2;
}
for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
if (gcry_mpi_scan(&mpi_e, GCRYMPI_FMT_USG,
keys[0].e, keys[0].len_e, NULL) ||
gcry_mpi_scan(&mpi_n, GCRYMPI_FMT_USG,
keys[0].n, keys[0].len_n, NULL)) {
fprintf(stderr, "failed to convert numbers\n");
return 2;
}
if (gcry_sexp_build(&rsa, NULL,
"(public-key (rsa (n %m) (e %m)))",
mpi_n, mpi_e)) {
fprintf(stderr, "failed to build rsa key\n");
return 2;
}
if (!gcry_pk_verify(signature, data, rsa)) {
ok = 1;
break;
}
}
if (!ok) {
fprintf(stderr, "Database signature wrong\n");
return 2;
}
#endif
num_countries = ntohl(header->reg_country_num);
countries = get_file_ptr(db, dblen,
......
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h> /* ntohl */
#include "regdb.h"
#ifdef USE_OPENSSL
#include <openssl/objects.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include "keys-ssl.c"
#endif
#ifdef USE_GCRYPT
#include <gcrypt.h>
#include "keys-gcrypt.c"
#endif
static void *get_file_ptr(__u8 *db, int dblen, int structlen, __be32 ptr)
{
__u32 p = ntohl(ptr);
......@@ -95,17 +79,6 @@ int main(int argc, char **argv)
struct regdb_file_header *header;
struct regdb_file_reg_country *countries;
int dblen, siglen, num_countries, i, j;
#ifdef USE_OPENSSL
RSA *rsa;
__u8 hash[SHA_DIGEST_LENGTH];
int ok = 0;
#endif
#ifdef USE_GCRYPT
gcry_mpi_t mpi_e, mpi_n;
gcry_sexp_t rsa, signature, data;
__u8 hash[20];
int ok = 0;
#endif
if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
......@@ -153,92 +126,8 @@ int main(int argc, char **argv)
}
/* verify signature */
#ifdef USE_OPENSSL
rsa = RSA_new();
if (!rsa) {
fprintf(stderr, "Failed to create RSA key\n");
return 2;
}
if (SHA1(db, dblen, hash) != hash) {
fprintf(stderr, "Failed to calculate SHA sum\n");
return 2;
}
for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
rsa->e = &keys[i].e;
rsa->n = &keys[i].n;
if (RSA_size(rsa) != siglen)
continue;
ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
db + dblen, siglen, rsa) == 1;
if (ok)
break;
}
if (!ok) {
fprintf(stderr, "Database signature wrong\n");
return 2;
}
rsa->e = NULL;
rsa->n = NULL;
RSA_free(rsa);
BN_print_fp(stdout, &keys[0].n);
return 0;
#endif
#ifdef USE_GCRYPT
/* initialise */
gcry_check_version(NULL);
/* hash the db */
gcry_md_hash_buffer(GCRY_MD_SHA1, hash, db, dblen);
if (gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))",
20, hash)) {
fprintf(stderr, "failed to build data expression\n");
return 2;
}
if (gcry_sexp_build(&signature, NULL, "(sig-val (rsa (s %b)))",
siglen, db + dblen)) {
fprintf(stderr, "failed to build signature expression\n");
return 2;
}
for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
if (gcry_mpi_scan(&mpi_e, GCRYMPI_FMT_USG,
keys[0].e, keys[0].len_e, NULL) ||
gcry_mpi_scan(&mpi_n, GCRYMPI_FMT_USG,
keys[0].n, keys[0].len_n, NULL)) {
fprintf(stderr, "failed to convert numbers\n");
return 2;
}
if (gcry_sexp_build(&rsa, NULL,
"(public-key (rsa (n %m) (e %m)))",
mpi_n, mpi_e)) {
fprintf(stderr, "failed to build rsa key\n");
return 2;
}
if (!gcry_pk_verify(signature, data, rsa)) {
ok = 1;
break;
}
}
if (!ok) {
fprintf(stderr, "Database signature wrong\n");
return 2;
}
#endif
if (!crda_verify_db_signature(db, dblen, siglen))
return -EINVAL;
num_countries = ntohl(header->reg_country_num);
countries = get_file_ptr(db, dblen,
......
#ifdef USE_OPENSSL
#include <stdio.h>
#include <openssl/objects.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#endif
#ifdef USE_GCRYPT
#include <stdio.h>
#include <gcrypt.h>
#endif
#include "regdb.h"
#ifdef USE_OPENSSL
#include "keys-ssl.c"
#endif
#ifdef USE_GCRYPT
#include "keys-gcrypt.c"
#endif
/*
* Checks the validity of the signature found on the regulatory
* database against the array 'keys'. Returns 1 if there exists
* at least one key in the array such that the signature is valid
* against that key; 0 otherwise.
*/
int crda_verify_db_signature(__u8 *db, int dblen, int siglen)
{
#ifdef USE_OPENSSL
RSA *rsa;
__u8 hash[SHA_DIGEST_LENGTH];
unsigned int i;
int ok = 0;
rsa = RSA_new();
if (!rsa) {
fprintf(stderr, "Failed to create RSA key.\n");
goto out;
}
if (SHA1(db, dblen, hash) != hash) {
fprintf(stderr, "Failed to calculate SHA1 sum.\n");
RSA_free(rsa);
goto out;
}
for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) {
rsa->e = &keys[i].e;
rsa->n = &keys[i].n;
if (RSA_size(rsa) != siglen)
continue;
ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
db + dblen, siglen, rsa) == 1;
}
rsa->e = NULL;
rsa->n = NULL;
RSA_free(rsa);
#endif
#ifdef USE_GCRYPT
gcry_mpi_t mpi_e, mpi_n;
gcry_sexp_t rsa, signature, data;
__u8 hash[20];
unsigned int i;
int ok = 0;
/* initialise */
gcry_check_version(NULL);
/* hash the db */
gcry_md_hash_buffer(GCRY_MD_SHA1, hash, db, dblen);
if (gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))",
20, hash)) {
fprintf(stderr, "Failed to build data S-expression.\n");
goto out;
}
if (gcry_sexp_build(&signature, NULL, "(sig-val (rsa (s %b)))",
siglen, db + dblen)) {
fprintf(stderr, "Failed to build signature S-expression.\n");
goto out;
}
for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) {
if (gcry_mpi_scan(&mpi_e, GCRYMPI_FMT_USG,
keys[0].e, keys[0].len_e, NULL) ||
gcry_mpi_scan(&mpi_n, GCRYMPI_FMT_USG,
keys[0].n, keys[0].len_n, NULL)) {
fprintf(stderr, "Failed to convert numbers.\n");
goto out;
}
if (gcry_sexp_build(&rsa, NULL,
"(public-key (rsa (n %m) (e %m)))",
mpi_n, mpi_e)) {
fprintf(stderr, "Failed to build RSA S-expression.\n");
goto out;
}
ok = gcry_pk_verify(signature, data, rsa) == 0;
}
#endif
#if defined(USE_OPENSSL) || defined(USE_GCRYPT)
if (!ok)
fprintf(stderr, "Database signature verification failed.\n");
out:
return ok;
#else
return 1;
#endif
}
......@@ -100,6 +100,10 @@ struct regdb_file_reg_country {
};
/* functions */
int crda_verify_db_signature(__u8 *db, int dblen, int siglen);
/*
* Verify that no unexpected padding is added to structures
* for some reason.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment