diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-08-16 22:50:56 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-08-24 23:49:09 +0200 |
commit | 7017a63132bc03462ba75e399c083e00f4e19573 (patch) | |
tree | ba790f1e3e542492640e6bf63ad1f3d6f62153e3 | |
parent | e536df1a394cf653ecc5964ece0551b0259abeb4 (diff) | |
download | cryptodev-linux-7017a63132bc03462ba75e399c083e00f4e19573.tar.gz cryptodev-linux-7017a63132bc03462ba75e399c083e00f4e19573.tar.xz cryptodev-linux-7017a63132bc03462ba75e399c083e00f4e19573.zip |
Convert *_SESSION_*
-rw-r--r-- | examples/ncr.c | 218 | ||||
-rw-r--r-- | examples/pk.c | 334 | ||||
-rw-r--r-- | examples/speed.c | 48 | ||||
-rw-r--r-- | ncr-int.h | 42 | ||||
-rw-r--r-- | ncr-pk.c | 150 | ||||
-rw-r--r-- | ncr-pk.h | 15 | ||||
-rw-r--r-- | ncr-sessions.c | 514 | ||||
-rw-r--r-- | ncr.c | 117 | ||||
-rw-r--r-- | ncr.h | 112 | ||||
-rw-r--r-- | utils.c | 37 |
10 files changed, 937 insertions, 650 deletions
diff --git a/examples/ncr.c b/examples/ncr.c index 49f5e38..facecd8 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -843,8 +843,18 @@ test_ncr_aes(int cfd) } kimport; uint8_t data[KEY_DATA_SIZE]; int i, j; - struct ncr_session_once_op_st nop; - int data_size; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } op; + size_t data_size; /* convert it to key */ key = ioctl(cfd, NCRIO_KEY_INIT); @@ -881,23 +891,30 @@ test_ncr_aes(int cfd) } /* encrypt */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_AES_ECB; - nop.init.key = key; - nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.udata.input = (void*)aes_vectors[i].plaintext; - nop.op.data.udata.input_size = 16; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_ENCRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = NCR_ALG_AES_ECB; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = key; + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = aes_vectors[i].plaintext; + op.input.data_size = 16; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &data_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - data_size = nop.op.data.udata.output_size; /* verify */ if (data_size != 16 || memcmp(data, aes_vectors[i].ciphertext, 16) != 0) { @@ -944,24 +961,30 @@ test_ncr_aes(int cfd) } /* decrypt */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_AES_ECB; - nop.init.key = key; - nop.init.op = NCR_OP_DECRYPT; - nop.op.data.udata.input = (void*)aes_vectors[i].ciphertext; - nop.op.data.udata.input_size = 16; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_DECRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = NCR_ALG_AES_ECB; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = key; + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = aes_vectors[i].ciphertext; + op.input.data_size = 16; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &data_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - data_size = nop.op.data.udata.output_size; - if (data_size != 16 || memcmp(data, aes_vectors[i].plaintext, 16) != 0) { fprintf(stderr, "AES test vector %d failed!\n", i); @@ -1084,8 +1107,19 @@ test_ncr_hash(int cfd) uint32_t flags ALIGN_NL; } kimport; uint8_t data[HASH_DATA_SIZE]; - int i, j, data_size; - struct ncr_session_once_op_st nop; + int i, j; + size_t data_size; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } op; /* convert it to key */ key = ioctl(cfd, NCRIO_KEY_INIT); @@ -1130,26 +1164,30 @@ test_ncr_hash(int cfd) } } - /* encrypt */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = hash_vectors[i].algorithm; - if (hash_vectors[i].key != NULL) - nop.init.key = key; - nop.init.op = hash_vectors[i].op; - nop.op.data.udata.input = (void*)hash_vectors[i].plaintext; - nop.op.data.udata.input_size = hash_vectors[i].plaintext_size; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = hash_vectors[i].op; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = hash_vectors[i].algorithm; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = hash_vectors[i].key != NULL ? key : NCR_KEY_INVALID; + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = hash_vectors[i].plaintext; + op.input.data_size = hash_vectors[i].plaintext_size; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &data_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - data_size = nop.op.data.udata.output_size; - if (data_size != hash_vectors[i].output_size || memcmp(data, hash_vectors[i].output, hash_vectors[i].output_size) != 0) { @@ -1178,6 +1216,7 @@ static int test_ncr_hash_key(int cfd) { ncr_key_t key; + ncr_session_t ses; struct __attribute__((packed)) { struct ncr_key_import f; struct nlattr id_head ALIGN_NL; @@ -1190,9 +1229,28 @@ test_ncr_hash_key(int cfd) uint32_t flags ALIGN_NL; } kimport; uint8_t data[HASH_DATA_SIZE]; - int j, data_size; - struct ncr_session_op_st op; - struct ncr_session_st op_init; + int j; + size_t data_size; + struct __attribute__((packed)) { + struct ncr_session_init f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + } op_init; + struct __attribute__((packed)) { + struct ncr_session_update f; + struct nlattr data_head ALIGN_NL; + struct ncr_session_input_data data ALIGN_NL; + } op_up_data; + struct __attribute__((packed)) { + struct ncr_session_update f; + struct nlattr key_head ALIGN_NL; + uint32_t key; + } op_up_key; + struct __attribute__((packed)) { + struct ncr_session_final f; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } op_final; const uint8_t *output = (void*)"\xe2\xd7\x2c\x2e\x14\xad\x97\xc8\xd2\xdb\xce\xd8\xb3\x52\x9f\x1c\xb3\x2c\x5c\xec"; /* convert it to key */ @@ -1230,58 +1288,62 @@ test_ncr_hash_key(int cfd) return 1; } - /* encrypt */ - memset(&op_init, 0, sizeof(op_init)); - op_init.algorithm = hash_vectors[0].algorithm; - op_init.op = hash_vectors[0].op; + memset(&op_init.f, 0, sizeof(op_init.f)); + op_init.f.input_size = sizeof(op_init); + op_init.f.op = hash_vectors[0].op; + op_init.algo_head.nla_len = NLA_HDRLEN + sizeof(op_init.algo); + op_init.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op_init.algo = hash_vectors[0].algorithm; - if (ioctl(cfd, NCRIO_SESSION_INIT, &op_init)) { + ses = ioctl(cfd, NCRIO_SESSION_INIT, &op_init); + if (ses < 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_INIT)"); return 1; } - memset(&op, 0, sizeof(op)); - op.ses = op_init.ses; - op.data.udata.input = (void*)hash_vectors[0].plaintext; - op.data.udata.input_size = hash_vectors[0].plaintext_size; - op.data.udata.output = NULL; - op.data.udata.output_size = 0; - op.type = NCR_DIRECT_DATA; + memset(&op_up_data.f, 0, sizeof(op_up_data.f)); + op_up_data.f.input_size = sizeof(op_up_data); + op_up_data.f.ses = ses; + op_up_data.data_head.nla_len = NLA_HDRLEN + sizeof(op_up_data.data); + op_up_data.data_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op_up_data.data.data = hash_vectors[0].plaintext; + op_up_data.data.data_size = hash_vectors[0].plaintext_size; - if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op)) { + if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op_up_data)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_UPDATE)"); return 1; } - memset(&op, 0, sizeof(op)); - op.ses = op_init.ses; - op.data.kdata.input = key; - op.data.kdata.output = NULL; - op.data.kdata.output_size = 0; - op.type = NCR_KEY_DATA; + memset(&op_up_key.f, 0, sizeof(op_up_key.f)); + op_up_key.f.input_size = sizeof(op_up_key); + op_up_key.f.ses = ses; + op_up_key.key_head.nla_len = NLA_HDRLEN + sizeof(op_up_key.key); + op_up_key.key_head.nla_type = NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA; + op_up_key.key = key; - if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op)) { + if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op_up_key)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_UPDATE)"); return 1; } - op.data.udata.input = NULL; - op.data.udata.input_size = 0; - op.data.udata.output = data; - op.data.udata.output_size = sizeof(data); - op.type = NCR_DIRECT_DATA; + memset(&op_final.f, 0, sizeof(op_final.f)); + op_final.f.input_size = sizeof(op_final); + op_final.f.ses = ses; + op_final.output_head.nla_len = NLA_HDRLEN + sizeof(op_final.output); + op_final.output_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + op_final.output.buffer = data; + op_final.output.buffer_size = sizeof(data); + op_final.output.result_size_ptr = &data_size; - if (ioctl(cfd, NCRIO_SESSION_FINAL, &op)) { + if (ioctl(cfd, NCRIO_SESSION_FINAL, &op_final)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_FINAL)"); return 1; } - data_size = op.data.udata.output_size; - if (data_size != hash_vectors[0].output_size || memcmp(data, output, hash_vectors[0].output_size) != 0) { diff --git a/examples/pk.c b/examples/pk.c index ac95820..8645fd4 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -794,10 +794,24 @@ test_ncr_wrap_key3(int cfd) static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oaep) { - struct ncr_session_once_op_st nop; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr rsa_head ALIGN_NL; + uint32_t rsa ALIGN_NL; + struct nlattr oaep_hash_head ALIGN_NL; + uint32_t oaep_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } op; uint8_t data[DATA_SIZE]; uint8_t vdata[RSA_ENCRYPT_SIZE]; - int enc_size; + size_t enc_size, dec_size; fprintf(stdout, "Tests on RSA (%s) key encryption:", (oaep!=0)?"OAEP":"PKCS V1.5"); fflush(stdout); @@ -806,55 +820,79 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae memcpy(vdata, data, sizeof(vdata)); /* do encryption */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_RSA; - nop.init.key = pubkey; + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_ENCRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = NCR_ALG_RSA; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = pubkey; + op.rsa_head.nla_len = NLA_HDRLEN + sizeof(op.rsa); + op.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; if (oaep) { - nop.init.params.params.rsa.type = RSA_PKCS1_OAEP; - nop.init.params.params.rsa.oaep_hash = NCR_ALG_SHA1; + op.rsa = RSA_PKCS1_OAEP; } else { - nop.init.params.params.rsa.type = RSA_PKCS1_V1_5; + op.rsa = RSA_PKCS1_V1_5; } - nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = RSA_ENCRYPT_SIZE; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + op.oaep_hash_head.nla_len = NLA_HDRLEN + sizeof(op.oaep_hash); + op.oaep_hash_head.nla_type = NCR_ATTR_RSA_OAEP_HASH_ALGORITHM; + op.oaep_hash = NCR_ALG_SHA1; /* Ignored if not using OAEP */ + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = data; + op.input.data_size = RSA_ENCRYPT_SIZE; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &enc_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - enc_size = nop.op.data.udata.output_size; /* decrypt data */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_RSA; - nop.init.key = privkey; - nop.init.op = NCR_OP_DECRYPT; + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_DECRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = NCR_ALG_RSA; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = privkey; + op.rsa_head.nla_len = NLA_HDRLEN + sizeof(op.rsa); + op.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; if (oaep) { - nop.init.params.params.rsa.type = RSA_PKCS1_OAEP; - nop.init.params.params.rsa.oaep_hash = NCR_ALG_SHA1; + op.rsa = RSA_PKCS1_OAEP; } else { - nop.init.params.params.rsa.type = RSA_PKCS1_V1_5; + op.rsa = RSA_PKCS1_V1_5; } - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = enc_size; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + op.oaep_hash_head.nla_len = NLA_HDRLEN + sizeof(op.oaep_hash); + op.oaep_hash_head.nla_type = NCR_ATTR_RSA_OAEP_HASH_ALGORITHM; + op.oaep_hash = NCR_ALG_SHA1; /* Ignored if not using OAEP */ + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = data; + op.input.data_size = enc_size; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &dec_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - if (memcmp(vdata, data, sizeof(vdata)) != 0) { + if (dec_size != sizeof(vdata) + || memcmp(vdata, data, sizeof(vdata)) != 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); fprintf(stderr, "Decrypted data do not match!\n"); return 1; @@ -870,61 +908,113 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int pss) { - struct ncr_session_once_op_st nop; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr rsa_head ALIGN_NL; + uint32_t rsa ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + uint32_t sign_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_output_buffer signature ALIGN_NL; + } ksign; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr rsa_head ALIGN_NL; + uint32_t rsa ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + uint32_t sign_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_input_data signature ALIGN_NL; + } kverify; uint8_t data[DATA_SIZE]; uint8_t sig[DATA_SIZE]; - int sig_size; + size_t sig_size; + int ret; fprintf(stdout, "Tests on RSA (%s) key signature:", (pss!=0)?"PSS":"PKCS V1.5"); fflush(stdout); memset(data, 0x3, sizeof(data)); - /* sign datad */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_RSA; - nop.init.key = privkey; - nop.init.params.params.rsa.type = (pss!=0)?RSA_PKCS1_PSS:RSA_PKCS1_V1_5; - nop.init.params.params.rsa.sign_hash = NCR_ALG_SHA1; - - nop.init.op = NCR_OP_SIGN; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = DATA_TO_SIGN; - nop.op.data.udata.output = sig; - nop.op.data.udata.output_size = sizeof(sig); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + /* sign data */ + memset(&ksign.f, 0, sizeof(ksign.f)); + ksign.f.input_size = sizeof(ksign); + ksign.f.op = NCR_OP_SIGN; + ksign.algo_head.nla_len = NLA_HDRLEN + sizeof(ksign.algo); + ksign.algo_head.nla_type = NCR_ATTR_ALGORITHM; + ksign.algo = NCR_ALG_RSA; + ksign.key_head.nla_len = NLA_HDRLEN + sizeof(ksign.key); + ksign.key_head.nla_type = NCR_ATTR_KEY; + ksign.key = privkey; + ksign.rsa_head.nla_len = NLA_HDRLEN + sizeof(ksign.rsa); + ksign.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; + ksign.rsa = (pss != 0) ? RSA_PKCS1_PSS : RSA_PKCS1_V1_5; + ksign.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(ksign.sign_hash); + ksign.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + ksign.sign_hash = NCR_ALG_SHA1; + ksign.input_head.nla_len = NLA_HDRLEN + sizeof(ksign.input); + ksign.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + ksign.input.data = data; + ksign.input.data_size = DATA_TO_SIGN; + ksign.signature_head.nla_len = NLA_HDRLEN + sizeof(ksign.signature); + ksign.signature_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + ksign.signature.buffer = sig; + ksign.signature.buffer_size = sizeof(sig); + ksign.signature.result_size_ptr = &sig_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &ksign)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - sig_size = nop.op.data.udata.output_size; /* verify signature */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_RSA; - nop.init.key = pubkey; - nop.init.params.params.rsa.type = (pss!=0)?RSA_PKCS1_PSS:RSA_PKCS1_V1_5; - nop.init.params.params.rsa.sign_hash = NCR_ALG_SHA1; - memset(data, 0x3, sizeof(data)); - nop.init.op = NCR_OP_VERIFY; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = DATA_TO_SIGN; - nop.op.data.udata.output = sig; - nop.op.data.udata.output_size = sig_size; - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&kverify.f, 0, sizeof(kverify.f)); + kverify.f.input_size = sizeof(kverify); + kverify.f.op = NCR_OP_VERIFY; + kverify.algo_head.nla_len = NLA_HDRLEN + sizeof(kverify.algo); + kverify.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kverify.algo = NCR_ALG_RSA; + kverify.key_head.nla_len = NLA_HDRLEN + sizeof(kverify.key); + kverify.key_head.nla_type = NCR_ATTR_KEY; + kverify.key = pubkey; + kverify.rsa_head.nla_len = NLA_HDRLEN + sizeof(kverify.rsa); + kverify.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; + kverify.rsa = (pss != 0) ? RSA_PKCS1_PSS : RSA_PKCS1_V1_5; + kverify.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(kverify.sign_hash); + kverify.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + kverify.sign_hash = NCR_ALG_SHA1; + kverify.input_head.nla_len = NLA_HDRLEN + sizeof(kverify.input); + kverify.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kverify.input.data = data; + kverify.input.data_size = DATA_TO_SIGN; + kverify.signature_head.nla_len = NLA_HDRLEN + sizeof(kverify.signature); + kverify.signature_head.nla_type = NCR_ATTR_FINAL_INPUT_DATA; + kverify.signature.data = sig; + kverify.signature.data_size = sig_size; + + ret = ioctl(cfd, NCRIO_SESSION_ONCE, &kverify); + if (ret < 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - if (nop.op.err == NCR_SUCCESS) + if (ret) fprintf(stdout, " Success\n"); else { fprintf(stdout, " Verification Failed!\n"); @@ -937,57 +1027,101 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey) { - struct ncr_session_once_op_st nop; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + uint32_t sign_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_output_buffer signature ALIGN_NL; + } ksign; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + uint32_t sign_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_input_data signature ALIGN_NL; + } kverify; uint8_t data[DATA_SIZE]; uint8_t sig[DATA_SIZE]; - int sig_size; + size_t sig_size; + int ret; fprintf(stdout, "Tests on DSA key signature:"); fflush(stdout); memset(data, 0x3, sizeof(data)); - /* sign datad */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_DSA; - nop.init.key = privkey; - nop.init.params.params.dsa.sign_hash = NCR_ALG_SHA1; - - nop.init.op = NCR_OP_SIGN; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = DATA_TO_SIGN; - nop.op.data.udata.output = sig; - nop.op.data.udata.output_size = sizeof(sig); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + /* sign data */ + memset(&ksign.f, 0, sizeof(ksign.f)); + ksign.f.input_size = sizeof(ksign); + ksign.f.op = NCR_OP_SIGN; + ksign.algo_head.nla_len = NLA_HDRLEN + sizeof(ksign.algo); + ksign.algo_head.nla_type = NCR_ATTR_ALGORITHM; + ksign.algo = NCR_ALG_DSA; + ksign.key_head.nla_len = NLA_HDRLEN + sizeof(ksign.key); + ksign.key_head.nla_type = NCR_ATTR_KEY; + ksign.key = privkey; + ksign.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(ksign.sign_hash); + ksign.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + ksign.sign_hash = NCR_ALG_SHA1; + ksign.input_head.nla_len = NLA_HDRLEN + sizeof(ksign.input); + ksign.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + ksign.input.data = data; + ksign.input.data_size = DATA_TO_SIGN; + ksign.signature_head.nla_len = NLA_HDRLEN + sizeof(ksign.signature); + ksign.signature_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + ksign.signature.buffer = sig; + ksign.signature.buffer_size = sizeof(sig); + ksign.signature.result_size_ptr = &sig_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &ksign)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - sig_size = nop.op.data.udata.output_size; /* verify signature */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_DSA; - nop.init.key = pubkey; - nop.init.params.params.dsa.sign_hash = NCR_ALG_SHA1; - - nop.init.op = NCR_OP_VERIFY; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = DATA_TO_SIGN; - nop.op.data.udata.output = sig; - nop.op.data.udata.output_size = sizeof(sig); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&kverify.f, 0, sizeof(kverify.f)); + kverify.f.input_size = sizeof(kverify); + kverify.f.op = NCR_OP_VERIFY; + kverify.algo_head.nla_len = NLA_HDRLEN + sizeof(kverify.algo); + kverify.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kverify.algo = NCR_ALG_DSA; + kverify.key_head.nla_len = NLA_HDRLEN + sizeof(kverify.key); + kverify.key_head.nla_type = NCR_ATTR_KEY; + kverify.key = pubkey; + kverify.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(kverify.sign_hash); + kverify.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + kverify.sign_hash = NCR_ALG_SHA1; + kverify.input_head.nla_len = NLA_HDRLEN + sizeof(kverify.input); + kverify.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kverify.input.data = data; + kverify.input.data_size = DATA_TO_SIGN; + kverify.signature_head.nla_len = NLA_HDRLEN + sizeof(kverify.signature); + kverify.signature_head.nla_type = NCR_ATTR_FINAL_INPUT_DATA; + kverify.signature.data = sig; + kverify.signature.data_size = sizeof(sig); + + ret = ioctl(cfd, NCRIO_SESSION_ONCE, &kverify); + if (ret < 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - if (nop.op.err == NCR_SUCCESS) + if (ret) fprintf(stdout, " Success\n"); else { fprintf(stdout, " Verification Failed!\n"); diff --git a/examples/speed.c b/examples/speed.c index 9c2e8b8..a75009e 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -88,7 +88,18 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) struct nlattr bits_head ALIGN_NL; uint32_t bits ALIGN_NL; } kgen; - struct ncr_session_once_op_st nop; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + struct nlattr iv_head ALIGN_NL; + } op; key = ioctl(cfd, NCRIO_KEY_INIT); if (key == -1) { @@ -127,17 +138,30 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) gettimeofday(&start, NULL); do { - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = algo; - nop.init.key = key; - nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.udata.input = buffer; - nop.op.data.udata.input_size = chunksize; - nop.op.data.udata.output = buffer; - nop.op.data.udata.output_size = chunksize; - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + size_t output_size; + + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_ENCRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = algo; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = key; + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = buffer; + op.input.data_size = chunksize; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = buffer; + op.output.buffer_size = chunksize; + op.output.result_size_ptr = &output_size; + op.iv_head.nla_len = NLA_HDRLEN + 0; + op.iv_head.nla_type = NCR_ATTR_IV; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; @@ -1,6 +1,7 @@ #ifndef NCR_INT_H # define NCR_INT_H +#include <linux/compat.h> #include <linux/idr.h> #include <linux/mutex.h> #include "ncr.h" @@ -170,10 +171,18 @@ void _ncr_sessions_item_put( struct session_item_st* item); struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc); void ncr_sessions_list_deinit(struct ncr_lists *lst); -int ncr_session_init(struct ncr_lists* lists, void __user* arg); -int ncr_session_update(struct ncr_lists* lists, void __user* arg); -int ncr_session_final(struct ncr_lists* lists, void __user* arg); -int ncr_session_once(struct ncr_lists* lists, void __user* arg); +int ncr_session_init(struct ncr_lists *lists, + const struct ncr_session_init *session, + struct nlattr *tb[]); +int ncr_session_update(struct ncr_lists *lists, + const struct ncr_session_update *op, struct nlattr *tb[], + int compat); +int ncr_session_final(struct ncr_lists *lists, + const struct ncr_session_final *op, struct nlattr *tb[], + int compat); +int ncr_session_once(struct ncr_lists *lists, + const struct ncr_session_once *once, struct nlattr *tb[], + int compat); /* master key */ extern struct key_item_st master_key; @@ -189,7 +198,30 @@ int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_it const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo); const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla); -const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params); int _ncr_key_get_sec_level(struct key_item_st* item); +/* CONFIG_COMPAT handling */ + +#ifdef CONFIG_COMPAT +struct compat_ncr_session_input_data { + compat_uptr_t data; + compat_size_t data_size; +}; + +struct compat_ncr_session_output_buffer { + compat_uptr_t buffer; + compat_size_t buffer_size; + compat_uptr_t result_size_ptr; +}; +#endif + +int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest, + const struct nlattr *nla, int compat); + +int ncr_session_output_buffer_from_nla(struct ncr_session_output_buffer *dest, + const struct nlattr *nla, int compat); + +int ncr_session_output_buffer_set_size(const struct ncr_session_output_buffer *dest, + size_t size, int compat); + #endif @@ -337,25 +337,6 @@ fail: return 0; } -const struct algo_properties_st *ncr_key_params_get_sign_hash( - const struct algo_properties_st *algo, - struct ncr_key_params_st * params) -{ - ncr_algorithm_t id; - - switch(algo->algo) { - case NCR_ALG_RSA: - id = params->params.rsa.sign_hash; - break; - case NCR_ALG_DSA: - id = params->params.dsa.sign_hash; - break; - default: - return ERR_PTR(-EINVAL); - } - return _ncr_algo_to_properties(id); -} - /* Encryption/Decryption */ @@ -368,9 +349,12 @@ void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx) } int ncr_pk_cipher_init(const struct algo_properties_st *algo, - struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, - struct key_item_st *key, const struct algo_properties_st *sign_hash) + struct ncr_pk_ctx* ctx, struct nlattr *tb[], + struct key_item_st *key, + const struct algo_properties_st *sign_hash) { + const struct nlattr *nla; + memset(ctx, 0, sizeof(*ctx)); if (key->algorithm != algo) { @@ -381,26 +365,38 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo, ctx->algorithm = algo; ctx->key = key; ctx->sign_hash = sign_hash; + ctx->salt_len = 0; switch(algo->algo) { case NCR_ALG_RSA: - if (params->params.rsa.type == RSA_PKCS1_V1_5) + nla = tb[NCR_ATTR_RSA_ENCODING_METHOD]; + if (nla == NULL) { + err(); + return -EINVAL; + } + switch (nla_get_u32(nla)) { + case RSA_PKCS1_V1_5: ctx->type = LTC_LTC_PKCS_1_V1_5; - else if (params->params.rsa.type == RSA_PKCS1_OAEP) { + break; + case RSA_PKCS1_OAEP: ctx->type = LTC_LTC_PKCS_1_OAEP; - ctx->oaep_hash = _ncr_algo_to_properties(params->params.rsa.oaep_hash); + nla = tb[NCR_ATTR_RSA_OAEP_HASH_ALGORITHM]; + ctx->oaep_hash = _ncr_nla_to_properties(nla); if (ctx->oaep_hash == NULL) { err(); return -EINVAL; } - } else if (params->params.rsa.type == RSA_PKCS1_PSS) { + break; + case RSA_PKCS1_PSS: ctx->type = LTC_LTC_PKCS_1_PSS; - } else { + nla = tb[NCR_ATTR_RSA_PSS_SALT_LENGTH]; + if (nla != NULL) + ctx->salt_len = nla_get_u32(nla); + break; + default: err(); return -EINVAL; } - - ctx->salt_len = params->params.rsa.pss_salt; break; case NCR_ALG_DSA: break; @@ -543,30 +539,11 @@ fail: return ret; } -int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, - const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, - struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size) +int ncr_pk_cipher_sign(const struct ncr_pk_ctx *ctx, const void *hash, + size_t hash_size, void *sig, size_t *sig_size) { -int cret, ret; -unsigned long osize = *osg_size; -uint8_t* tmp; -void * input, *output; - - tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL); - if (tmp == NULL) { - err(); - return -ENOMEM; - } - - input = tmp; - output = &tmp[isg_size]; - - ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, input, isg_size); - if (ret != isg_size) { - err(); - ret = -EINVAL; - goto fail; - } + int cret; + unsigned long osize = *sig_size; switch(ctx->algorithm->algo) { case NCR_ALG_RSA: @@ -574,63 +551,35 @@ void * input, *output; err(); return -EINVAL; } - cret = rsa_sign_hash_ex( input, isg_size, output, &osize, + cret = rsa_sign_hash_ex(hash, hash_size, sig, &osize, ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); return _ncr_tomerr(cret); } - *osg_size = osize; + *sig_size = osize; break; case NCR_ALG_DSA: - cret = dsa_sign_hash( input, isg_size, output, &osize, + cret = dsa_sign_hash(hash, hash_size, sig, &osize, &ctx->key->key.pk.dsa); if (cret != CRYPT_OK) { err(); return _ncr_tomerr(cret); } - *osg_size = osize; + *sig_size = osize; break; default: err(); - ret = -EINVAL; - goto fail; - } - - ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size); - if (ret != *osg_size) { - err(); - ret = -EINVAL; - goto fail; + return -EINVAL; } - ret = 0; -fail: - kfree(tmp); - - return ret; + return 0; } -int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, - const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size, - const void* hash, size_t hash_size, ncr_error_t* err) +int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const void *sig, + size_t sig_size, const void *hash, size_t hash_size) { -int cret, ret; -int stat = 0; -uint8_t* sig; - - sig = kmalloc(sign_sg_size, GFP_KERNEL); - if (sig == NULL) { - err(); - return -ENOMEM; - } - - ret = sg_copy_to_buffer((struct scatterlist*)sign_sg, sign_sg_cnt, sig, sign_sg_size); - if (ret != sign_sg_size) { - err(); - ret = -EINVAL; - goto fail; - } + int cret, ret, stat; switch(ctx->algorithm->algo) { case NCR_ALG_RSA: @@ -638,35 +587,28 @@ uint8_t* sig; err(); return -EINVAL; } - cret = rsa_verify_hash_ex( sig, sign_sg_size, - hash, hash_size, ctx->type, ctx->sign_hash, - ctx->salt_len, &stat, &ctx->key->key.pk.rsa); + cret = rsa_verify_hash_ex(sig, sig_size, hash, + hash_size, ctx->type, + ctx->sign_hash, ctx->salt_len, + &stat, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); ret = _ncr_tomerr(cret); goto fail; } - if (stat == 1) - *err = 0; - else - *err = NCR_VERIFICATION_FAILED; - + ret = (stat == 1); break; case NCR_ALG_DSA: - cret = dsa_verify_hash( sig, sign_sg_size, - hash, hash_size, &stat, &ctx->key->key.pk.dsa); + cret = dsa_verify_hash(sig, sig_size, hash, hash_size, + &stat, &ctx->key->key.pk.dsa); if (cret != CRYPT_OK) { err(); ret = _ncr_tomerr(cret); goto fail; } - if (stat == 1) - *err = 0; - else - *err = NCR_VERIFICATION_FAILED; - + ret = (stat == 1); break; default: err(); @@ -674,9 +616,7 @@ uint8_t* sig; goto fail; } - ret = 0; fail: - kfree(sig); return ret; } @@ -28,8 +28,9 @@ int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_ /* encryption/decryption */ int ncr_pk_cipher_init(const struct algo_properties_st *algo, - struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, - struct key_item_st *key, const struct algo_properties_st *sign_hash); + struct ncr_pk_ctx* ctx, struct nlattr *tb[], + struct key_item_st *key, + const struct algo_properties_st *sign_hash); void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx); int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx, @@ -40,13 +41,11 @@ int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx, const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size); -int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, - const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, - struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size); +int ncr_pk_cipher_sign(const struct ncr_pk_ctx *ctx, const void *hash, + size_t hash_size, void *sig, size_t *sig_size); -int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, - const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size, - const void* hash, size_t hash_size, ncr_error_t* err); +int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const void *sig, + size_t sig_size, const void *hash, size_t hash_size); int _ncr_tomerr(int err); diff --git a/ncr-sessions.c b/ncr-sessions.c index 320a061..8f3e721 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -31,7 +31,8 @@ #include <linux/scatterlist.h> #include <net/netlink.h> -static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); +static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[]); static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); static int session_list_deinit_fn(int id, void *item, void *unused) @@ -222,8 +223,28 @@ const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla return _ncr_algo_to_properties(nla_get_u32(nla)); } -static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* session) +static int key_item_get_nla_read(struct key_item_st **st, + struct ncr_lists *lists, + const struct nlattr *nla) { + int ret; + + if (nla == NULL) { + err(); + return -EINVAL; + } + ret = ncr_key_item_get_read(st, lists, nla_get_u32(nla)); + if (ret < 0) { + err(); + return ret; + } + return ret; +} + +static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, + struct nlattr *tb[]) +{ + const struct nlattr *nla; struct session_item_st* ns = NULL; int ret; const struct algo_properties_st *sign_hash; @@ -234,15 +255,15 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses return -ENOMEM; } - ns->op = session->op; - ns->algorithm = _ncr_algo_to_properties(session->algorithm); + ns->op = op; + ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); if (ns->algorithm == NULL) { err(); ret = -EINVAL; goto fail; } - switch(session->op) { + switch(op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: if (!ns->algorithm->can_encrypt) { @@ -252,7 +273,8 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } /* read key */ - ret = ncr_key_item_get_read( &ns->key, lists, session->key); + ret = key_item_get_nla_read(&ns->key, lists, + tb[NCR_ATTR_KEY]); if (ret < 0) { err(); goto fail; @@ -269,7 +291,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses if (ns->key->type == NCR_KEY_TYPE_SECRET) { int keysize = ns->key->key.secret.size; - if (session->algorithm == NCR_ALG_NULL) + if (ns->algorithm->algo == NCR_ALG_NULL) keysize = 0; if (ns->algorithm->kstr == NULL) { @@ -286,16 +308,19 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } if (ns->algorithm->needs_iv) { - if (session->params.params.cipher.iv_size > sizeof(session->params.params.cipher.iv)) { + nla = tb[NCR_ATTR_IV]; + if (nla == NULL) { err(); ret = -EINVAL; goto fail; } - cryptodev_cipher_set_iv(&ns->cipher, session->params.params.cipher.iv, session->params.params.cipher.iv_size); + cryptodev_cipher_set_iv(&ns->cipher, + nla_data(nla), + nla_len(nla)); } } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) { ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key, NULL); + tb, ns->key, NULL); if (ret < 0) { err(); goto fail; @@ -330,7 +355,8 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } else { /* read key */ - ret = ncr_key_item_get_read( &ns->key, lists, session->key); + ret = key_item_get_nla_read(&ns->key, lists, + tb[NCR_ATTR_KEY]); if (ret < 0) { err(); goto fail; @@ -359,10 +385,11 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } } else if (ns->algorithm->is_pk && (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC)) { - sign_hash = ncr_key_params_get_sign_hash(ns->key->algorithm, &session->params); - if (IS_ERR(sign_hash)) { + nla = tb[NCR_ATTR_SIGNATURE_HASH_ALGORITHM]; + sign_hash = _ncr_nla_to_properties(nla); + if (sign_hash == NULL) { err(); - ret = PTR_ERR(sign_hash); + ret = -EINVAL; goto fail; } @@ -379,7 +406,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key, sign_hash); + tb, ns->key, sign_hash); if (ret < 0) { err(); goto fail; @@ -404,8 +431,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses goto fail; } - ret = 0; - session->ses = ns->desc; + ret = ns->desc; fail: if (ret < 0) { @@ -416,29 +442,11 @@ fail: return ret; } -int ncr_session_init(struct ncr_lists* lists, void __user* arg) +int ncr_session_init(struct ncr_lists *lists, + const struct ncr_session_init *session, + struct nlattr *tb[]) { - struct ncr_session_st session; - int ret; - - if (unlikely(copy_from_user(&session, arg, sizeof(session)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_init(lists, &session); - if (unlikely(ret)) { - err(); - return ret; - } - - ret = copy_to_user( arg, &session, sizeof(session)); - if (unlikely(ret)) { - err(); - _ncr_session_remove(lists, session.ses); - return -EFAULT; - } - return ret; + return _ncr_session_init(lists, session->op, tb); } static int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, @@ -542,66 +550,64 @@ static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) return 0; } -/* Only the output buffer is given as scatterlist */ -static int get_userbuf1(struct session_item_st* ses, - void __user * udata, size_t udata_size, struct scatterlist **dst_sg, unsigned *dst_cnt) +/* Make NCR_ATTR_UPDATE_INPUT_DATA and NCR_ATTR_UPDATE_OUTPUT_BUFFER available + in scatterlists */ +static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], + struct scatterlist **src_sg, unsigned *src_cnt, + size_t *src_size, struct ncr_session_output_buffer *dst, + struct scatterlist **dst_sg, unsigned *dst_cnt, + int compat) { - int pagecount = 0; - - if (unlikely(udata == NULL)) { - err(); - return -EINVAL; - } + const struct nlattr *src_nla, *dst_nla; + struct ncr_session_input_data src; + int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1, ret; + size_t input_size; - pagecount = PAGECOUNT(udata, udata_size); - _ncr_session_grow_pages(ses, pagecount); + src_nla = tb[NCR_ATTR_UPDATE_INPUT_DATA]; + dst_nla = tb[NCR_ATTR_UPDATE_OUTPUT_BUFFER]; - if (__get_userbuf(udata, udata_size, 1, - pagecount, ses->pages, ses->sg)) { + ret = ncr_session_input_data_from_nla(&src, src_nla, compat); + if (unlikely(ret != 0)) { err(); - return -EINVAL; + return ret; } - (*dst_sg) = ses->sg; - *dst_cnt = pagecount; + *src_size = src.data_size; - ses->available_pages = pagecount; - - return 0; -} - -/* make op->data.udata.input and op->data.udata.output available in scatterlists */ -static int get_userbuf2(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **src_sg, - unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; - size_t input_size = op->data.udata.input_size; - - if (unlikely(op->data.udata.input == NULL)) { - err(); - return -EINVAL; + if (dst_nla != NULL) { + ret = ncr_session_output_buffer_from_nla(dst, dst_nla, compat); + if (unlikely(ret != 0)) { + err(); + return ret; + } } - src_pagecount = PAGECOUNT(op->data.udata.input, input_size); + input_size = src.data_size; + src_pagecount = PAGECOUNT(src.data, input_size); - if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ + if (dst_nla == NULL || src.data != dst->buffer) { /* non-in-situ transformation */ write_src = 0; - if (op->data.udata.output != NULL) { - dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + if (dst_nla != NULL) { + dst_pagecount = PAGECOUNT(dst->buffer, + dst->buffer_size); } else { dst_pagecount = 0; } } else { - src_pagecount = max((int)(PAGECOUNT(op->data.udata.output, op->data.udata.output_size)), - src_pagecount); - input_size = max(input_size, (size_t)op->data.udata.output_size); + src_pagecount = max((int)(PAGECOUNT(dst->buffer, + dst->buffer_size)), + src_pagecount); + input_size = max(input_size, dst->buffer_size); } pagecount = src_pagecount + dst_pagecount; - _ncr_session_grow_pages(ses, pagecount); + ret = _ncr_session_grow_pages(ses, pagecount); + if (ret != 0) { + err(); + return ret; + } - if (__get_userbuf(op->data.udata.input, input_size, write_src, - src_pagecount, ses->pages, ses->sg)) { + if (__get_userbuf((void __user *)src.data, input_size, write_src, + src_pagecount, ses->pages, ses->sg)) { err(); printk("write: %d\n", write_src); return -EINVAL; @@ -613,14 +619,15 @@ static int get_userbuf2(struct session_item_st* ses, *dst_cnt = dst_pagecount; (*dst_sg) = ses->sg + src_pagecount; - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, - ses->pages + src_pagecount, *dst_sg)) { + if (__get_userbuf(dst->buffer, dst->buffer_size, 1, + dst_pagecount, ses->pages + src_pagecount, + *dst_sg)) { err(); release_user_pages(ses->pages, src_pagecount); return -EINVAL; } } else { - if (op->data.udata.output != NULL) { + if (dst_nla != NULL) { *dst_cnt = src_pagecount; (*dst_sg) = (*src_sg); } else { @@ -635,16 +642,18 @@ static int get_userbuf2(struct session_item_st* ses, } /* Called when userspace buffers are used */ -static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { int ret; struct session_item_st* sess; - struct scatterlist *isg; - struct scatterlist *osg; + struct scatterlist *isg = NULL; + struct scatterlist *osg = NULL; unsigned osg_cnt=0, isg_cnt=0; - size_t isg_size, osg_size; + size_t isg_size = 0, osg_size; + struct ncr_session_output_buffer out; - sess = ncr_sessions_item_get(lists, op->ses); + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; @@ -656,13 +665,12 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st return -ERESTARTSYS; } - ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); + ret = get_userbuf2(sess, tb, &isg, &isg_cnt, &isg_size, &out, &osg, + &osg_cnt, compat); if (ret < 0) { err(); goto fail; } - isg_size = op->data.udata.input_size; - osg_size = op->data.udata.output_size; switch(sess->op) { case NCR_OP_ENCRYPT: @@ -672,6 +680,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } + osg_size = out.buffer_size; if (osg_size < isg_size) { err(); ret = -EINVAL; @@ -684,8 +693,13 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st err(); goto fail; } - op->data.udata.output_size = osg_size; - + + ret = ncr_session_output_buffer_set_size(&out, osg_size, + compat); + if (ret != 0) { + err(); + goto fail; + } break; case NCR_OP_DECRYPT: if (osg == NULL) { @@ -694,6 +708,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } + osg_size = out.buffer_size; if (osg_size < isg_size) { err(); ret = -EINVAL; @@ -706,8 +721,13 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st err(); goto fail; } - op->data.udata.output_size = osg_size; + ret = ncr_session_output_buffer_set_size(&out, osg_size, + compat); + if (ret != 0) { + err(); + goto fail; + } break; case NCR_OP_SIGN: @@ -737,40 +757,34 @@ fail: return ret; } -static int try_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int try_session_update(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { - if (op->type == NCR_KEY_DATA) { - if (op->data.kdata.input != NCR_KEY_INVALID) - return _ncr_session_update_key(lists, op); - } else if (op->type == NCR_DIRECT_DATA) { - if (op->data.udata.input != NULL) - return _ncr_session_update(lists, op); - } + if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) + return _ncr_session_update_key(lists, ses, tb); + else if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) + return _ncr_session_update(lists, ses, tb, compat); return 0; } -static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { + const struct nlattr *nla; int ret; struct session_item_st* sess; int digest_size; uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; - uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; - struct scatterlist *osg; - unsigned osg_cnt=0; - size_t osg_size = 0; - size_t orig_osg_size; - void __user * udata = NULL; - size_t *udata_size; - - sess = ncr_sessions_item_get(lists, op->ses); + void *buffer = NULL; + + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; } - ret = try_session_update(lists, op); + ret = try_session_update(lists, ses, tb, compat); if (ret < 0) { err(); _ncr_sessions_item_put(sess); @@ -782,129 +796,138 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* _ncr_sessions_item_put(sess); return -ERESTARTSYS; } - - if (op->type == NCR_DIRECT_DATA) { - udata = op->data.udata.output; - udata_size = &op->data.udata.output_size; - } else if (op->type == NCR_KEY_DATA) { - udata = op->data.kdata.output; - udata_size = &op->data.kdata.output_size; - } else { - err(); - ret = -EINVAL; - goto fail; - } switch(sess->op) { - case NCR_OP_ENCRYPT: - case NCR_OP_DECRYPT: - break; - case NCR_OP_VERIFY: - ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); + case NCR_OP_ENCRYPT: + case NCR_OP_DECRYPT: + break; + case NCR_OP_VERIFY: { + struct ncr_session_input_data src; + + nla = tb[NCR_ATTR_FINAL_INPUT_DATA]; + ret = ncr_session_input_data_from_nla(&src, nla, compat); + if (unlikely(ret != 0)) { + err(); + goto fail; + } + + buffer = kmalloc(src.data_size, GFP_KERNEL); + if (buffer == NULL) { + err(); + ret = -ENOMEM; + goto fail; + } + if (unlikely(copy_from_user(buffer, src.data, src.data_size))) { + err(); + ret = -EFAULT; + goto fail; + } + + digest_size = sess->hash.digestsize; + if (digest_size == 0 || sizeof(digest) < digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + if (!sess->algorithm->is_pk) + ret = (digest_size == src.data_size + && memcmp(buffer, digest, digest_size) == 0); + else { + ret = ncr_pk_cipher_verify(&sess->pk, buffer, + src.data_size, digest, + digest_size); if (ret < 0) { err(); goto fail; } - orig_osg_size = osg_size = *udata_size; + } + break; + } - digest_size = sess->hash.digestsize; - if (digest_size == 0 || sizeof(digest) < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { + case NCR_OP_SIGN: { + struct ncr_session_output_buffer dst; + size_t output_size; + + nla = tb[NCR_ATTR_FINAL_OUTPUT_BUFFER]; + ret = ncr_session_output_buffer_from_nla(&dst, nla, compat); + if (unlikely(ret != 0)) { + err(); + goto fail; + } + + digest_size = sess->hash.digestsize; + if (digest_size == 0) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + cryptodev_hash_deinit(&sess->hash); + + if (!sess->algorithm->is_pk) { + if (dst.buffer_size < digest_size) { err(); + ret = -ERANGE; goto fail; } - - if (sess->algorithm->is_hmac) { - ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - if (digest_size != osg_size || - memcmp(vdigest, digest, digest_size) != 0) { - - op->err = NCR_VERIFICATION_FAILED; - } else { - op->err = NCR_SUCCESS; - } - } else { - /* PK signature */ - ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, - digest, digest_size, &op->err); - if (ret < 0) { - err(); - goto fail; - } - } - break; - - case NCR_OP_SIGN: - ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); - if (ret < 0) { + if (unlikely(copy_to_user(dst.buffer, digest, + digest_size))) { err(); + ret = -EFAULT; goto fail; } - orig_osg_size = osg_size = *udata_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || osg_size < digest_size) { + output_size = digest_size; + } else { + output_size = dst.buffer_size; + buffer = kmalloc(output_size, GFP_KERNEL); + if (buffer == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - - ret = cryptodev_hash_final(&sess->hash, digest); + ret = ncr_pk_cipher_sign(&sess->pk, digest, digest_size, + buffer, &output_size); if (ret < 0) { err(); goto fail; } - - ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); - if (ret != digest_size) { + if (unlikely(copy_to_user(dst.buffer, buffer, + output_size))) { err(); - ret = -EINVAL; + ret = -EFAULT; goto fail; } - osg_size = digest_size; - - cryptodev_hash_deinit(&sess->hash); + } - if (sess->algorithm->is_pk) { - /* PK signature */ - - ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, - osg, osg_cnt, &orig_osg_size); - if (ret < 0) { - err(); - goto fail; - } - osg_size = orig_osg_size; - } - break; - default: + ret = ncr_session_output_buffer_set_size(&dst, output_size, + compat); + if (ret != 0) { err(); - ret = -EINVAL; goto fail; + } + break; + } + default: + err(); + ret = -EINVAL; + goto fail; } - - if (osg_size > 0) - *udata_size = osg_size; - - ret = 0; fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } mutex_unlock(&sess->mem_mutex); + kfree(buffer); cryptodev_hash_deinit(&sess->hash); if (sess->algorithm->is_symmetric) { @@ -914,27 +937,28 @@ fail: } _ncr_sessions_item_put(sess); - _ncr_session_remove(lists, op->ses); + _ncr_session_remove(lists, ses); return ret; } /* Direct with key: Allows to hash a key */ -/* Called when userspace buffers are used */ -static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[]) { int ret; struct session_item_st* sess; struct key_item_st* key = NULL; - sess = ncr_sessions_item_get(lists, op->ses); + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; } /* read key */ - ret = ncr_key_item_get_read( &key, lists, op->data.kdata.input); + ret = key_item_get_nla_read(&key, lists, + tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA]); if (ret < 0) { err(); goto fail; @@ -976,20 +1000,16 @@ fail: return ret; } -int ncr_session_update(struct ncr_lists* lists, void __user* arg) +int ncr_session_update(struct ncr_lists *lists, + const struct ncr_session_update *op, struct nlattr *tb[], + int compat) { - struct ncr_session_op_st op; int ret; - if (unlikely(copy_from_user( &op, arg, sizeof(op)))) { - err(); - return -EFAULT; - } - - if (op.type == NCR_DIRECT_DATA) - ret = _ncr_session_update(lists, &op); - else if (op.type == NCR_KEY_DATA) - ret = _ncr_session_update_key(lists, &op); + if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) + ret = _ncr_session_update(lists, op->ses, tb, compat); + else if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) + ret = _ncr_session_update_key(lists, op->ses, tb); else ret = -EINVAL; @@ -998,61 +1018,33 @@ int ncr_session_update(struct ncr_lists* lists, void __user* arg) return ret; } - if (unlikely(copy_to_user(arg, &op, sizeof(op)))) { - err(); - return -EFAULT; - } - return 0; } -int ncr_session_final(struct ncr_lists* lists, void __user* arg) +int ncr_session_final(struct ncr_lists *lists, + const struct ncr_session_final *op, struct nlattr *tb[], + int compat) { - struct ncr_session_op_st op; - int ret; - - if (unlikely(copy_from_user(&op, arg, sizeof(op)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_final(lists, &op); - if (unlikely(ret)) { - err(); - return ret; - } - - if (unlikely(copy_to_user(arg, &op, sizeof(op)))) { - err(); - return -EFAULT; - } - return 0; + return _ncr_session_final(lists, op->ses, tb, compat); } -int ncr_session_once(struct ncr_lists* lists, void __user* arg) +int ncr_session_once(struct ncr_lists *lists, + const struct ncr_session_once *once, struct nlattr *tb[], + int compat) { - struct ncr_session_once_op_st kop; int ret; - if (unlikely(copy_from_user(&kop, arg, sizeof(kop)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_init(lists, &kop.init); + ret = _ncr_session_init(lists, once->op, tb); if (ret < 0) { err(); return ret; } - kop.op.ses = kop.init.ses; - ret = _ncr_session_final(lists, &kop.op); + ret = _ncr_session_final(lists, ret, tb, compat); if (ret < 0) { err(); return ret; } - if (unlikely(copy_to_user(arg, &kop, sizeof(kop)))) - return -EFAULT; - return 0; + return ret; } @@ -32,6 +32,7 @@ #include <linux/scatterlist.h> #include <linux/cred.h> #include <linux/capability.h> +#include <net/netlink.h> #include "ncr.h" #include "ncr-int.h" #include "utils.h" @@ -129,7 +130,7 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) BUG(); switch (cmd) { -#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ +#define CASE_(LABEL, STRUCT, FUNCTION, ARGS) \ case (LABEL): { \ struct STRUCT data; \ \ @@ -138,9 +139,13 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) err(); \ return PTR_ERR(attr_buf); \ } \ - ret = (FUNCTION)(lst, &data, tb); \ + ret = (FUNCTION)ARGS; \ break; \ } +#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ + CASE_(LABEL, STRUCT, FUNCTION, (lst, &data, tb)) +#define CASE_NO_OUTPUT_COMPAT(LABEL, STRUCT, FUNCTION) \ + CASE_(LABEL, STRUCT, FUNCTION, (lst, &data, tb, 0)) case NCRIO_KEY_INIT: return ncr_key_init(lst); @@ -184,20 +189,21 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) ncr_key_storage_wrap); CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap, ncr_key_storage_unwrap); - case NCRIO_SESSION_INIT: - return ncr_session_init(lst, arg); - case NCRIO_SESSION_UPDATE: - return ncr_session_update(lst, arg); - case NCRIO_SESSION_FINAL: - return ncr_session_final(lst, arg); - case NCRIO_SESSION_ONCE: - return ncr_session_once(lst, arg); + CASE_NO_OUTPUT(NCRIO_SESSION_INIT, ncr_session_init, ncr_session_init); + CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_UPDATE, ncr_session_update, + ncr_session_update); + CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_FINAL, ncr_session_final, + ncr_session_final); + CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_ONCE, ncr_session_once, + ncr_session_once); case NCRIO_MASTER_KEY_SET: return ncr_master_key_set(arg); default: return -EINVAL; +#undef CASE_ #undef CASE_NO_OUTPUT +#undef CASE_NO_OUTPUT_COMPAT } kfree(attr_buf); return ret; @@ -330,6 +336,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_KEY_DERIVE: case NCRIO_KEY_GET_INFO: case NCRIO_KEY_DEINIT: + case NCRIO_SESSION_INIT: return ncr_ioctl(lst, cmd, arg_); #define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ @@ -347,6 +354,19 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) break; \ } +#define CASE_COMPAT_ONLY(LABEL, STRUCT, FUNCTION) \ + case (LABEL): { \ + struct STRUCT data; \ + \ + attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&data, tb, arg); \ + if (IS_ERR(attr_buf)) { \ + err(); \ + return PTR_ERR(attr_buf); \ + } \ + ret = (FUNCTION)(lst, &data, tb, 1); \ + break; \ + } + CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap); @@ -355,11 +375,88 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) ncr_key_storage_wrap); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap, ncr_key_storage_unwrap); + CASE_COMPAT_ONLY(NCRIO_SESSION_UPDATE, ncr_session_update, + ncr_session_update); + CASE_COMPAT_ONLY(NCRIO_SESSION_FINAL, ncr_session_final, + ncr_session_final); + CASE_COMPAT_ONLY(NCRIO_SESSION_ONCE, ncr_session_once, + ncr_session_once); default: return -EINVAL; #undef CASE_NO_OUTPUT +#undef CASE_COMPAT_ONLY } kfree(attr_buf); return ret; } #endif + +int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest, + const struct nlattr *nla, int compat) +{ + if (unlikely(nla == NULL)) + return -EINVAL; +#ifdef CONFIG_COMPAT + if (!compat) { +#endif + if (unlikely(nla_len(nla) < sizeof(dest))) + return -ERANGE; /* nla_validate would return -ERANGE. */ + memcpy(dest, nla_data(nla), sizeof(*dest)); +#ifdef CONFIG_COMPAT + } else { + struct compat_ncr_session_input_data old; + + if (unlikely(nla_len(nla) < sizeof(old))) + return -ERANGE; + memcpy(&old, nla_data(nla), sizeof(old)); + dest->data = compat_ptr(old.data); + dest->data_size = old.data_size; + } +#endif + return 0; +} + +int ncr_session_output_buffer_from_nla(struct ncr_session_output_buffer *dest, + const struct nlattr *nla, int compat) +{ + if (unlikely(nla == NULL)) + return -EINVAL; +#ifdef CONFIG_COMPAT + if (!compat) { +#endif + if (unlikely(nla_len(nla) < sizeof(dest))) + return -ERANGE; /* nla_validate would return -ERANGE. */ + memcpy(dest, nla_data(nla), sizeof(*dest)); +#ifdef CONFIG_COMPAT + } else { + struct compat_ncr_session_output_buffer old; + + if (unlikely(nla_len(nla) < sizeof(old))) + return -ERANGE; + memcpy(&old, nla_data(nla), sizeof(old)); + dest->buffer = compat_ptr(old.buffer); + dest->buffer_size = old.buffer_size; + dest->result_size_ptr = compat_ptr(old.result_size_ptr); + } +#endif + return 0; +} + + +int ncr_session_output_buffer_set_size(const struct ncr_session_output_buffer *dest, + size_t size, int compat) +{ +#ifdef CONFIG_COMPAT + if (!compat) +#endif + return put_user(size, dest->result_size_ptr); +#ifdef CONFIG_COMPAT + else { + compat_size_t old; + + old = size; + return put_user(old, + (compat_size_t __user *)dest->result_size_ptr); + } +#endif +} @@ -33,7 +33,16 @@ enum { /* FIXME: Use NLA_STRING for this, later */ NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_SIGNATURE_HASH_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_WRAPPING_ALGORITHM, /* NLA_U32 - ncr_wrap_algorithm_t */ + NCR_ATTR_UPDATE_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */ + /* NLA_BINARY - ncr_session_output_buffer */ + NCR_ATTR_UPDATE_OUTPUT_BUFFER, + NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA, /* NLA_U32 - ncr_key_t */ + NCR_ATTR_FINAL_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */ + /* NLA_BINARY - ncr_session_output_buffer */ + NCR_ATTR_FINAL_OUTPUT_BUFFER, + NCR_ATTR_KEY, /* NLA_U32 - ncr_key_t */ NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */ NCR_ATTR_KEY_ID, /* NLA_BINARY */ NCR_ATTR_KEY_TYPE, /* NLA_U32 - ncr_key_type_t */ @@ -41,6 +50,9 @@ enum { NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */ NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */ NCR_ATTR_RSA_E, /* NLA_BINARY */ + NCR_ATTR_RSA_ENCODING_METHOD, /* NLA_U32 - ncr_rsa_type_t */ + NCR_ATTR_RSA_OAEP_HASH_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_RSA_PSS_SALT_LENGTH, /* NLA_U32 */ NCR_ATTR_DSA_P_BITS, /* NLA_U32 */ NCR_ATTR_DSA_Q_BITS, /* NLA_U32 */ NCR_ATTR_DH_PRIME, /* NLA_BINARY */ @@ -142,29 +154,6 @@ typedef enum { RSA_PKCS1_PSS, /* for signatures only */ } ncr_rsa_type_t; -/* used in encryption - */ -struct ncr_key_params_st { - /* this structure always corresponds to a key. Hence the - * parameters of the union selected are based on the corresponding - * key */ - union { - struct { - __u8 iv[NCR_CIPHER_MAX_BLOCK_LEN]; - __kernel_size_t iv_size; - } cipher; - struct { - ncr_rsa_type_t type; - ncr_algorithm_t oaep_hash; /* for OAEP */ - ncr_algorithm_t sign_hash; /* for signatures */ - unsigned int pss_salt; /* PSS signatures */ - } rsa; - struct { - ncr_algorithm_t sign_hash; /* for signatures */ - } dsa; - } params; -}; - typedef enum { NCR_DERIVE_DH=1, } ncr_derive_t; @@ -283,65 +272,46 @@ typedef enum { typedef __s32 ncr_session_t; #define NCR_SESSION_INVALID ((ncr_session_t)-1) -/* input of CIOCGSESSION */ -struct ncr_session_st { - /* input */ - ncr_algorithm_t algorithm; - - ncr_key_t key; - struct ncr_key_params_st params; - ncr_crypto_op_t op; - - /* output */ - ncr_session_t ses; /* session identifier */ +struct ncr_session_input_data { + const void __user *data; + __kernel_size_t data_size; }; -typedef enum { - NCR_SUCCESS = 0, - NCR_ERROR_GENERIC = -1, - NCR_VERIFICATION_FAILED = -2, -} ncr_error_t; +struct ncr_session_output_buffer { + void __user *buffer; + __kernel_size_t buffer_size; + __kernel_size_t __user *result_size_ptr; +}; -typedef enum { - NCR_KEY_DATA, - NCR_DIRECT_DATA, -} ncr_data_type_t; +struct ncr_session_init { + __u32 input_size, output_size; + __u32 op; /* ncr_crypto_op_t */ + __NL_ATTRIBUTES; +}; -struct ncr_session_op_st { - /* input */ +struct ncr_session_update { + __u32 input_size, output_size; ncr_session_t ses; + __NL_ATTRIBUTES; +}; - union { - struct { - ncr_key_t input; - void __user * output; /* when verifying signature this is - * the place of the signature. - */ - __kernel_size_t output_size; - } kdata; /* NCR_KEY_DATA */ - struct { - void __user * input; - __kernel_size_t input_size; - void __user * output; - __kernel_size_t output_size; - } udata; /* NCR_DIRECT_DATA */ - } data; - ncr_data_type_t type; - - /* output of verification */ - ncr_error_t err; +struct ncr_session_final { + __u32 input_size, output_size; + ncr_session_t ses; + __NL_ATTRIBUTES; }; -struct ncr_session_once_op_st { - struct ncr_session_st init; - struct ncr_session_op_st op; +struct ncr_session_once { + __u32 input_size, output_size; + ncr_crypto_op_t op; + __NL_ATTRIBUTES; }; -#define NCRIO_SESSION_INIT _IOR ('c', 300, struct ncr_session_st) -#define NCRIO_SESSION_UPDATE _IOWR ('c', 301, struct ncr_session_op_st) -#define NCRIO_SESSION_FINAL _IOWR ('c', 302, struct ncr_session_op_st) +#define NCRIO_SESSION_INIT _IOWR('c', 300, struct ncr_session_init) +#define NCRIO_SESSION_UPDATE _IOWR('c', 301, struct ncr_session_update) +#define NCRIO_SESSION_FINAL _IOWR('c', 302, struct ncr_session_final) /* everything in one call */ -#define NCRIO_SESSION_ONCE _IOWR ('c', 303, struct ncr_session_once_op_st) +#define NCRIO_SESSION_ONCE _IOWR('c', 303, struct ncr_session_once) #endif @@ -28,10 +28,44 @@ #include "ncr-int.h" #include "utils.h" +#ifdef CONFIG_COMPAT +/* max() is too clever for compile-time constants */ +#define CONST_MAX(A, B) ((A) > (B) ? (A) : (B)) + +#define MAX_SESSION_INPUT_DATA_SIZE \ + (CONST_MAX(sizeof(struct ncr_session_input_data), \ + sizeof(struct compat_ncr_session_input_data))) +#define MAX_SESSION_OUTPUT_BUFFER_SIZE \ + (CONST_MAX(sizeof(struct ncr_session_output_buffer), \ + sizeof(struct compat_ncr_session_output_buffer))) + +#else /* !CONFIG_COMPAT */ + +#define MAX_SESSION_INPUT_DATA_SIZE (sizeof(struct ncr_session_input_data)) +#define MAX_SESSION_OUTPUT_BUFFER_SIZE \ + (sizeof(struct ncr_session_output_buffer)) + +#endif /* !CONFIG_COMPAT */ + static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_SIGNATURE_HASH_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_WRAPPING_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_UPDATE_INPUT_DATA] = { + NLA_BINARY, MAX_SESSION_INPUT_DATA_SIZE + }, + [NCR_ATTR_UPDATE_OUTPUT_BUFFER] = { + NLA_BINARY, MAX_SESSION_OUTPUT_BUFFER_SIZE + }, + [NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] = { NLA_U32, 0 }, + [NCR_ATTR_FINAL_INPUT_DATA] = { + NLA_BINARY, MAX_SESSION_INPUT_DATA_SIZE + }, + [NCR_ATTR_FINAL_OUTPUT_BUFFER] = { + NLA_BINARY, MAX_SESSION_OUTPUT_BUFFER_SIZE + }, + [NCR_ATTR_KEY] = { NLA_U32, 0 }, [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 }, [NCR_ATTR_KEY_ID] = { NLA_BINARY, 0 }, [NCR_ATTR_KEY_TYPE] = { NLA_U32, 0 }, @@ -39,6 +73,9 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_E] = { NLA_BINARY, 0 }, + [NCR_ATTR_RSA_ENCODING_METHOD] = { NLA_U32, 0 }, + [NCR_ATTR_RSA_OAEP_HASH_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_RSA_PSS_SALT_LENGTH] = { NLA_U32, 0 }, [NCR_ATTR_DSA_P_BITS] = { NLA_U32, 0 }, [NCR_ATTR_DSA_Q_BITS] = { NLA_U32, 0 }, [NCR_ATTR_DH_PRIME] = { NLA_BINARY, 0 }, |