53
53
#include <linux/ctype.h>
54
54
#include <linux/nl80211.h>
55
55
#include <linux/platform_device.h>
56
+ #include <linux/verification.h>
56
57
#include <linux/moduleparam.h>
57
58
#include <linux/firmware.h>
58
59
#include <net/cfg80211.h>
@@ -659,6 +660,115 @@ static bool valid_country(const u8 *data, unsigned int size,
659
660
return true;
660
661
}
661
662
663
+ #ifdef CONFIG_CFG80211_REQUIRE_SIGNED_REGDB
664
+ static struct key * builtin_regdb_keys ;
665
+
666
+ static void __init load_keys_from_buffer (const u8 * p , unsigned int buflen )
667
+ {
668
+ const u8 * end = p + buflen ;
669
+ size_t plen ;
670
+ key_ref_t key ;
671
+
672
+ while (p < end ) {
673
+ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
674
+ * than 256 bytes in size.
675
+ */
676
+ if (end - p < 4 )
677
+ goto dodgy_cert ;
678
+ if (p [0 ] != 0x30 &&
679
+ p [1 ] != 0x82 )
680
+ goto dodgy_cert ;
681
+ plen = (p [2 ] << 8 ) | p [3 ];
682
+ plen += 4 ;
683
+ if (plen > end - p )
684
+ goto dodgy_cert ;
685
+
686
+ key = key_create_or_update (make_key_ref (builtin_regdb_keys , 1 ),
687
+ "asymmetric" , NULL , p , plen ,
688
+ ((KEY_POS_ALL & ~KEY_POS_SETATTR ) |
689
+ KEY_USR_VIEW | KEY_USR_READ ),
690
+ KEY_ALLOC_NOT_IN_QUOTA |
691
+ KEY_ALLOC_BUILT_IN |
692
+ KEY_ALLOC_BYPASS_RESTRICTION );
693
+ if (IS_ERR (key )) {
694
+ pr_err ("Problem loading in-kernel X.509 certificate (%ld)\n" ,
695
+ PTR_ERR (key ));
696
+ } else {
697
+ pr_notice ("Loaded X.509 cert '%s'\n" ,
698
+ key_ref_to_ptr (key )-> description );
699
+ key_ref_put (key );
700
+ }
701
+ p += plen ;
702
+ }
703
+
704
+ return ;
705
+
706
+ dodgy_cert :
707
+ pr_err ("Problem parsing in-kernel X.509 certificate list\n" );
708
+ }
709
+
710
+ static int __init load_builtin_regdb_keys (void )
711
+ {
712
+ builtin_regdb_keys =
713
+ keyring_alloc (".builtin_regdb_keys" ,
714
+ KUIDT_INIT (0 ), KGIDT_INIT (0 ), current_cred (),
715
+ ((KEY_POS_ALL & ~KEY_POS_SETATTR ) |
716
+ KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH ),
717
+ KEY_ALLOC_NOT_IN_QUOTA , NULL , NULL );
718
+ if (IS_ERR (builtin_regdb_keys ))
719
+ return PTR_ERR (builtin_regdb_keys );
720
+
721
+ pr_notice ("Loading compiled-in X.509 certificates for regulatory database\n" );
722
+
723
+ #ifdef CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS
724
+ load_keys_from_buffer (shipped_regdb_certs , shipped_regdb_certs_len );
725
+ #endif
726
+ #ifdef CFG80211_EXTRA_REGDB_KEYDIR
727
+ if (CONFIG_CFG80211_EXTRA_REGDB_KEYDIR [0 ] != '\0' )
728
+ load_keys_from_buffer (extra_regdb_certs , extra_regdb_certs_len );
729
+ #endif
730
+
731
+ return 0 ;
732
+ }
733
+
734
+ static bool regdb_has_valid_signature (const u8 * data , unsigned int size )
735
+ {
736
+ const struct firmware * sig ;
737
+ bool result ;
738
+
739
+ if (request_firmware (& sig , "regulatory.db.p7s" , & reg_pdev -> dev ))
740
+ return false;
741
+
742
+ result = verify_pkcs7_signature (data , size , sig -> data , sig -> size ,
743
+ builtin_regdb_keys ,
744
+ VERIFYING_UNSPECIFIED_SIGNATURE ,
745
+ NULL , NULL ) == 0 ;
746
+
747
+ release_firmware (sig );
748
+
749
+ return result ;
750
+ }
751
+
752
+ static void free_regdb_keyring (void )
753
+ {
754
+ key_put (builtin_regdb_keys );
755
+ }
756
+ #else
757
+ static int load_builtin_regdb_keys (void )
758
+ {
759
+ return 0 ;
760
+ }
761
+
762
+ static bool regdb_has_valid_signature (const u8 * data , unsigned int size )
763
+ {
764
+ return true;
765
+ }
766
+
767
+ static void free_regdb_keyring (void )
768
+ {
769
+ }
770
+ #endif /* CONFIG_CFG80211_REQUIRE_SIGNED_REGDB */
771
+
662
772
static bool valid_regdb (const u8 * data , unsigned int size )
663
773
{
664
774
const struct fwdb_header * hdr = (void * )data ;
@@ -673,6 +783,9 @@ static bool valid_regdb(const u8 *data, unsigned int size)
673
783
if (hdr -> version != cpu_to_be32 (FWDB_VERSION ))
674
784
return false;
675
785
786
+ if (!regdb_has_valid_signature (data , size ))
787
+ return false;
788
+
676
789
country = & hdr -> country [0 ];
677
790
while ((u8 * )(country + 1 ) <= data + size ) {
678
791
if (!country -> coll_ptr )
@@ -773,7 +886,7 @@ static void regdb_fw_cb(const struct firmware *fw, void *context)
773
886
pr_info ("failed to load regulatory.db\n" );
774
887
set_error = - ENODATA ;
775
888
} else if (!valid_regdb (fw -> data , fw -> size )) {
776
- pr_info ("loaded regulatory.db is malformed\n" );
889
+ pr_info ("loaded regulatory.db is malformed or signature is missing/invalid \n" );
777
890
set_error = - EINVAL ;
778
891
}
779
892
@@ -3535,6 +3648,10 @@ int __init regulatory_init(void)
3535
3648
{
3536
3649
int err = 0 ;
3537
3650
3651
+ err = load_builtin_regdb_keys ();
3652
+ if (err )
3653
+ return err ;
3654
+
3538
3655
reg_pdev = platform_device_register_simple ("regulatory" , 0 , NULL , 0 );
3539
3656
if (IS_ERR (reg_pdev ))
3540
3657
return PTR_ERR (reg_pdev );
@@ -3611,4 +3728,6 @@ void regulatory_exit(void)
3611
3728
3612
3729
if (!IS_ERR_OR_NULL (regdb ))
3613
3730
kfree (regdb );
3731
+
3732
+ free_regdb_keyring ();
3614
3733
}
0 commit comments