2016-12-11 1 views
0

Je travaille sur un module noyau qui utilise un chiffrement asymétrique du noyau crypto api, version 4.8.0 du noyau. Je génère des paires de clés asymétriques par openssl, les convertis au format DER (que je savais être un sous-ensemble de BER), et le code dans mon module. La clé privée fonctionne très bien, mais la clé publique échoue toujours à crypto_akcipher_set_pub_key, même si j'essaie d'autres paires de clés. dmesg qu'afficher:crypto_akcipher_set_pub_key dans le noyau crypto asymétrique renvoie toujours l'erreur

[16891.604718] next_op: pc=0/10 dp=0/161 C=0 J=0 
[16891.604721] - match? 30 30 00 
[16891.604724] - TAG: 30 158 CONS 
[16891.604726] next_op: pc=2/10 dp=3/161 C=1 J=0 
[16891.604727] - match? 30 02 32 
[16891.604729] 
       ASN1: Unexpected tag [m=2 d=4 ot=02 t=30 l=158] 
[16891.604730] set key error! -74,,,,,0 

Voici mes questions:

A) Est-ce que dmesg signifient la clé publique est erronée? Comment générer une paire de clés compatible kernel-crypto? B) Je ne trouve pas de paires de clés RSA utilisables pour le chiffrement asymétrique du noyau, même pas dans Linux/crypto/testmgr.h ou libkcapi/test/test.sh, pouvez-vous m'aider?

Merci!

Voici mon module:

#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/crypto.h> 
#include <linux/scatterlist.h> 
#include <linux/gfp.h> 
#include <linux/err.h> 
#include <linux/syscalls.h> 
#include <linux/slab.h> 
#include <crypto/skcipher.h> 
#include <crypto/akcipher.h> 
#include <linux/random.h> 
#include <linux/delay.h> 
#include <linux/highmem.h> 
const char *priv_key = 
    "\x30\x82\x02\x5d\x02\x01\x00\x02\x81\x81\x00\xd0" 
    "\xb4\x5a\xc1\x9e\x2e\x4d\xae\xbd\x51\x39\xcc\x4b" 
    "\x12\xf5\x76\x30\xcf\x39\x97\xf1\xd3\x0d\xaa\x37" 
    "\x70\x2d\x2f\x01\xc9\x69\x09\xe3\x4e\xd5\x90\x68" 
    "\xfe\xbf\x7c\x8b\x86\xdf\xf3\x14\xb3\x96\xcf\x1b" 
    "\x39\xe3\xe6\x8a\x77\x6d\xe4\x89\xef\xdb\xba\x4a" 
    "\x40\x6d\xa9\xec\x21\x62\x00\xa4\xc3\x45\xcc\xdd" 
    "\x56\xb2\x77\x59\x46\x17\x27\x0e\x2c\xfe\x85\x53" 
    "\x72\x26\x9b\xdc\x24\x83\xd1\x67\xa7\x4c\x88\x70" 
    "\x78\x3f\x1c\x60\xd4\x95\x14\x57\xfc\xdb\x15\xaa" 
    "\xab\x31\x32\xb2\x44\x72\xdd\xb0\x0b\x13\x62\x03" 
    "\x50\x1d\xd4\x6a\xf6\xb2\x23\x02\x03\x01\x00\x01" 
    "\x02\x81\x80\x7b\x83\x10\xe6\xde\xf7\x26\x30\x10" 
    "\x88\x3e\x7d\x61\xbc\xa1\x99\xc5\xbf\x0d\xa5\x97" 
    "\x8e\xc0\xda\x88\x9e\x91\x8e\xed\x2e\xc6\x43\xfc" 
    "\xcb\x0d\xe6\xbd\xcc\x6d\x84\x86\x8a\x56\x84\xe4" 
    "\x2e\x78\x44\xaf\x27\x2e\x71\xa4\x66\x93\x99\x99" 
    "\xec\x62\x8c\x38\x1f\x33\x06\x37\xc1\x9d\x17\x6b" 
    "\xad\xfb\x8e\x44\xd3\x11\xcb\x74\xa4\x01\x78\xb0" 
    "\x9c\x64\xd3\x0d\x63\x99\x65\xe3\xca\xae\x11\xb2" 
    "\xc4\x00\x36\xc2\xfc\x4b\x7b\x6f\x9e\x84\xb6\x97" 
    "\x00\x56\x5b\x09\xa1\x28\xf5\x28\x8d\xc7\x93\x45" 
    "\xba\xc0\x6b\xa9\x2d\xeb\x02\xcd\xde\x1e\x29\x02" 
    "\x41\x00\xf6\x0e\x41\xbc\xfa\x40\x82\xba\xa0\x6a" 
    "\xa5\x75\x5c\xcd\xfe\xa8\x11\xa6\xef\xbc\xad\x5f" 
    "\x86\x40\xb4\x5a\x65\xc1\x7b\x5e\x89\xc2\x60\x38" 
    "\x0e\x8b\x7d\x7d\x99\x30\x01\xf1\xea\x1e\x3e\x46" 
    "\xf4\xd2\xd9\x80\xaf\x3a\x4b\x2f\xbb\x91\xbb\xb7" 
    "\x22\x2d\x6a\x0f\x4e\x6f\x02\x41\x00\xd9\x23\xa7" 
    "\x98\x0c\x58\xe1\x5d\xa7\x15\x05\xc6\xd9\x7b\xc5" 
    "\x7b\xd3\x01\x8b\x1e\xf1\x2e\x99\xc5\xac\x41\xf1" 
    "\x92\x88\xd9\x8e\x50\x86\xf9\x2f\x66\x42\xeb\xf9" 
    "\x80\x78\xfa\xc7\xea\x63\x35\x7e\x6f\xc5\x35\x36" 
    "\x6b\xa1\x8a\xa3\x49\x97\xbc\xa6\x9b\x5c\x6e\xf1" 
    "\x8d\x02\x40\x44\x70\xa0\xbe\x64\xc9\x4e\xd3\x84" 
    "\x4d\x45\xaa\x88\x5e\xcf\xe7\x85\xc9\x6e\x43\x87" 
    "\xe1\xdb\x20\xe2\x49\x86\xa6\x33\x9f\x8f\x27\xde" 
    "\xc5\x98\xde\x19\xd0\xb6\xac\x50\xce\x2e\x35\xad" 
    "\x52\xe5\x44\x44\xb5\x73\x87\xfe\x63\xcf\x83\x70" 
    "\xb8\x36\xac\x75\x24\xbe\xc7\x02\x41\x00\x87\xd2" 
    "\x97\xa8\xb2\x40\x7e\x67\xf8\x75\x5b\xf1\xb0\x64" 
    "\x8d\x79\x10\xd9\xec\x4d\xe4\x8b\x43\xc0\xb4\x29" 
    "\x63\x94\x47\x69\xde\x6d\x5c\xa0\x4e\x17\xe7\x50" 
    "\x77\xf6\xf6\xb5\xd7\x8b\x33\x97\x68\x89\x3d\x90" 
    "\x35\x84\x49\xbd\xd0\xb9\xdd\xe2\x31\x4d\x09\x1a" 
    "\x94\x99\x02\x41\x00\xc9\x12\xec\x64\xe9\x01\x27" 
    "\x10\x6c\xad\xc5\x83\x8a\x26\x39\xe0\x05\xde\xde" 
    "\xf9\x1a\x5d\xf6\xcb\xe8\xd2\x9b\x40\xd5\x11\xc8" 
    "\x9a\x6d\x29\xb6\x15\x36\x9a\xee\x45\xe2\x51\x14" 
    "\xa8\x2d\xab\x57\x86\x80\x87\x0a\x02\xaf\xfa\xda" 
    "\x5e\x7d\xfb\x84\xd1\x3a\xe0\xed\x57"; 
const int priv_key_len = 609; 

const char *pub_key = 
    "\x30\x81\x9e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7" 
    "\x0d\x01\x01\x01\x05\x00\x03\x81\x8c\x00\x30\x81" 
    "\x88\x02\x81\x80\x6d\x4d\xaf\xf5\x32\x98\xfa\x33" 
    "\xf2\x4a\xb0\x50\x27\x6f\x50\x0b\x28\xca\x5f\x6e" 
    "\xde\xec\x7b\xae\xeb\xd1\x89\xdf\xcf\x8d\x12\x6c" 
    "\x0d\xf2\x32\x65\xb7\x04\xf2\xb8\x76\x67\xe9\x28" 
    "\xc3\x12\x6b\x4a\x52\x09\xd6\x61\x9b\x21\x25\x04" 
    "\xe0\x9a\xec\xbc\x25\x3f\xfc\x6f\x1a\x98\xa8\x02" 
    "\xa8\x2e\x89\x91\x20\xcf\xf0\xd1\x9d\x09\x35\xac" 
    "\x95\xe2\xe4\x8e\x5b\x7c\x34\x93\x39\x4f\x33\xbd" 
    "\x6e\xe7\xc5\xbb\x2a\x28\x32\x13\x62\x39\x37\x87" 
    "\x40\xe7\x59\xf8\x94\xad\xc4\x2e\xaf\x23\xf4\x98" 
    "\xcd\x90\x27\x96\x41\xc6\x4a\xcd\x6d\x56\xfd\x5b" 
    "\x02\x03\x01\x00\x01"; 
const int pub_key_len = 161; 

const char *msg = "\x54\x85\x9b\x34\x2c\x49\xea\x2a"; 
const int msg_len = 8; 

char *crypted = NULL; 
int crypted_len = 0; 

struct tcrypt_result { 
    struct completion completion; 
    int err; 
}; 

struct akcipher_testvec { 
    unsigned char *key; 
    unsigned char *msg; 
    unsigned int key_size; 
    unsigned int msg_size; 
}; 

static inline void hexdump(unsigned char *buf,unsigned int len) { 
    while(len--) 
     printk("%02x",*buf++); 
    printk("\n"); 
} 

static void tcrypt_complete(struct crypto_async_request *req, int err) 
{ 
    struct tcrypt_result *res = req->data; 

    if (err == -EINPROGRESS) 
     return; 

    res->err = err; 
    complete(&res->completion); 
} 

static int wait_async_op(struct tcrypt_result *tr, int ret) 
{ 
    if (ret == -EINPROGRESS || ret == -EBUSY) { 
     wait_for_completion(&tr->completion); 
     reinit_completion(&tr->completion); 
     ret = tr->err; 
    } 
    return ret; 
} 

static int uf_akcrypto(struct crypto_akcipher *tfm, 
         void *data, int datalen, int phase) 
{ 
    void *xbuf = NULL; 
    struct akcipher_request *req; 
    void *outbuf = NULL; 
    struct tcrypt_result result; 
    unsigned int out_len_max = 0; 
    struct scatterlist src, dst; 

    int err = -ENOMEM; 
    xbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); 
    if (!xbuf) 
     return err; 

    req = akcipher_request_alloc(tfm, GFP_KERNEL); 
    if (!req) 
     goto free_xbuf; 

    init_completion(&result.completion); 


    if (!phase) //test 
     err = crypto_akcipher_set_pub_key(tfm, pub_key, pub_key_len); 
    else 
     err = crypto_akcipher_set_priv_key(tfm, priv_key, priv_key_len); 

// err = crypto_akcipher_set_priv_key(tfm, priv_key, priv_key_len); 
    if (err){ 
     printk("set key error! %d,,,,,%d\n", err,phase); 
     goto free_req; 
    } 

    err = -ENOMEM; 
    out_len_max = crypto_akcipher_maxsize(tfm); 
    outbuf = kzalloc(out_len_max, GFP_KERNEL); 
    if (!outbuf) 
     goto free_req; 

    if (WARN_ON(datalen > PAGE_SIZE)) 
     goto free_all; 

    memcpy(xbuf, data, datalen); 
    sg_init_one(&src, xbuf, datalen); 
    sg_init_one(&dst, outbuf, out_len_max); 
    akcipher_request_set_crypt(req, &src, &dst, datalen, out_len_max); 
    akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 
           tcrypt_complete, &result); 

    if (phase){ 
     err = wait_async_op(&result, crypto_akcipher_encrypt(req)); 
     if (err) { 
      pr_err("alg: akcipher: encrypt test failed. err %d\n", err); 
      goto free_all; 
     } 
     memcpy(crypted,outbuf,out_len_max); 
     crypted_len = out_len_max; 
     hexdump(crypted, out_len_max); 
    }else{ 
     err = wait_async_op(&result, crypto_akcipher_decrypt(req)); 
     if (err) { 
      pr_err("alg: akcipher: decrypt test failed. err %d\n", err); 
      goto free_all; 
     } 
     hexdump(outbuf, out_len_max); 
    } 

free_all: 
    kfree(outbuf); 
free_req: 
    akcipher_request_free(req); 
free_xbuf: 
    kfree(xbuf); 
    return err; 
} 


static int userfaultfd_akcrypto(void *data, int datalen, int phase) 
{ 
    struct crypto_akcipher *tfm; 
    int err = 0; 

    tfm = crypto_alloc_akcipher("rsa", CRYPTO_ALG_INTERNAL, 0); 
    if (IS_ERR(tfm)) { 
      pr_err("alg: akcipher: Failed to load tfm for rsa: %ld\n", PTR_ERR(tfm)); 
      return PTR_ERR(tfm); 
    } 
    err = uf_akcrypto(tfm,data,datalen,phase); 

    crypto_free_akcipher(tfm); 
    return err; 
} 

static int __init test_init(void) 
{ 
    crypted = kmalloc(PAGE_SIZE, GFP_KERNEL); 
    if (!crypted){ 
     printk("crypted kmalloc error\n"); 
     return -1; 
    } 

    userfaultfd_akcrypto(msg,msg_len,1); 
    userfaultfd_akcrypto(crypted,crypted_len,0); 
    kfree(crypted); 
} 

static void __exit test_exit(void) 
{ 

} 

module_init(test_init); 
module_exit(test_exit); 

MODULE_LICENSE("GPL"); 

Répondre

0

J'ai compris cela moi-même.

Le fait est que la clé publique générée par openssl est correcte, mais elle contient plus d'informations en tête, ce qui n'est pas requis par kernel crypto api. Avec les données supplémentaires, kernel ctypto api ne peut pas analyser correctement la structure de la clé publique, c'est pourquoi "ASN1: Balise inattendue".

Jetez un oeil à clé publique compatible avec le noyau here, il ne contient que les éléments suivants:

{ 
    total size 
    integer size and value 
    integer size and value 
} 

La commande suivante vous montrera la structure de la clé publique dans der formate générer par OpenSSL:

openssl asn1parse -in public_key.der -inform DER 

Les sorties sont comme celles-ci:

0:d=0 hl=3 l= 159 cons: SEQUENCE   
3:d=1 hl=2 l= 13 cons: SEQUENCE   
5:d=2 hl=2 l= 9 prim: OBJECT   :rsaEncryption 
16:d=2 hl=2 l= 0 prim: NULL    
18:d=1 hl=3 l= 141 prim: BIT STRING 

Les données réelles sont dans BIT STRING. Et son décalage est de 18. Donc, de l'offset 18 à la fin, il y a les données que vous vouliez.

Vous pouvez lire la structure BIT STRING intérieure en tapant la commande suivante:

openssl asn1parse -in public_key.der -inform DER -strparse 18 

Les sorties comme:

0:d=0 hl=3 l= 137 cons: SEQUENCE   
3:d=1 hl=3 l= 129 prim: INTEGER   :D0B45AC19E2E4DA .... 
135:d=1 hl=2 l= 3 prim: INTEGER   :010001 

tout comme la même structure que la clé publique compatible avec le noyau.