Browse code

linux-secure: added LKCM driver

Change-Id: I5e3d6831d97a2a54b55425ab94a69dbacb15b6a9
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/2186
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Anish Swaminathan <anishs@vmware.com>

Alexey Makhalov authored on 2017/03/25 16:24:02
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,1149 @@
0
+diff -Naur LKCM/drv_fips_test.c LKCM.new/drv_fips_test.c
1
+--- LKCM/drv_fips_test.c	1970-01-01 00:00:00.000000000 +0000
2
+@@ -0,0 +1,174 @@
3
++#include <linux/kernel.h>
4
++#include <linux/module.h>
5
++#include <linux/init.h>
6
++#include <linux/fs.h>
7
++#include <asm/uaccess.h>
8
++#include <crypto/hash.h>
9
++#include <crypto/aes.h>
10
++#include <crypto/algapi.h>
11
++#include <linux/crypto.h>
12
++#include <linux/init.h>
13
++#include <linux/types.h>
14
++#include <linux/errno.h>
15
++#include <linux/err.h>
16
++#include <linux/crypto.h>
17
++#include <linux/ctype.h>
18
++#include <linux/vmalloc.h>
19
++#include <asm/byteorder.h>
20
++
21
++#include "test_harness_ioctl.h"
22
++#include "fips_test.h"
23
++
24
++static test_data_v1_t *user_data;
25
++static int user_data_size = sizeof(test_data_v1_t) + (1024*1024*3);
26
++int g_debug_level;
27
++
28
++DEFINE_MUTEX(lock);
29
++
30
++static bool is_cipher(int algo)
31
++{
32
++	switch (algo) {
33
++        case AESCBC_GEN:
34
++        case AESCBC_NI:
35
++        case AESECB:
36
++        case AESECB_GEN:
37
++        case AESXTS:
38
++        case AESXTS_GEN:
39
++        case TDES_CBC:
40
++        case TDES_ECB:
41
++		return true;
42
++	default:
43
++		return false;
44
++	}
45
++}
46
++
47
++static long test_harness_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
48
++{
49
++	int ret = -EINVAL;
50
++	int sz;
51
++	trace_debug(TRACE_FUNCTION, "Entered\n");
52
++	printk("Inside IOCTL\n");
53
++
54
++	mutex_lock(&lock);
55
++	switch(cmd){
56
++	case IOCTL_SET_VECTOR:
57
++		trace_debug(TRACE_DEBUG, "Using Vector\n");
58
++		if(copy_from_user(user_data, (test_data_v1_t*)arg, sizeof(test_data_v1_t))) {
59
++			printk("Failed to copy data header from user\n");
60
++			ret = -EINTR;
61
++			break;
62
++		}
63
++		sz = test_data_v1_sz(user_data);
64
++		if ((sz <= 0) || (sz > user_data_size)) {
65
++			printk("invalid data size: %d, valid range (1 to %d)\n", sz, user_data_size);
66
++			ret = -E2BIG;
67
++			break;
68
++		}
69
++		if(copy_from_user(user_data, (test_data_v1_t*)arg, sz) ){
70
++			printk("Failed to copy data from user\n");
71
++			ret = -EINTR;
72
++			break;
73
++		}
74
++		if ((user_data->klen < 0) || (user_data->klen > KEY_SIZE)) {
75
++			printk("invalid key size: %d, valid range (0 to %d)\n", user_data->klen, KEY_SIZE);
76
++			ret = -E2BIG;
77
++			break;
78
++		}
79
++		if ((user_data->iv_len < 0) || (user_data->iv_len > MAX_IVLEN)) {
80
++			printk("invalid iv size: %d, valid range (0 to %d)\n", user_data->iv_len, MAX_IVLEN);
81
++			ret = -E2BIG;
82
++			break;
83
++		}
84
++
85
++		if (is_cipher(user_data->algo)) {
86
++			ret = crypt_test_cipher(user_data->algo, user_data->mode,
87
++						user_data->test_key, user_data->klen,
88
++						user_data->test_iv, user_data->iv_len,
89
++						user_data->test_data, user_data->data_len);
90
++
91
++		} else {
92
++			ret = crypt_test_hash(user_data->algo,
93
++					      user_data->test_key, user_data->klen,
94
++					      user_data->test_data, user_data->data_len,
95
++					      user_data->test_data, &user_data->data_len);
96
++		}
97
++		user_data->status = ret;
98
++        sz = test_data_v1_sz(user_data);        // Update size again (needed when data length output > input)
99
++		if(copy_to_user((void *) arg, user_data, sz)) {
100
++			trace_debug(TRACE_ERR, "Failed to copy data from user\n");
101
++			ret = -EINTR;
102
++			break;
103
++		}
104
++
105
++		ret = 0;
106
++	break;
107
++	}
108
++	mutex_unlock(&lock);
109
++	return ret;
110
++}
111
++
112
++static int dev_open(struct inode *inod, struct file *fil)
113
++{
114
++	printk("KERN_ALERT device opened");
115
++	return 0;
116
++}
117
++
118
++static ssize_t dev_read(struct file *filep,char *buf,size_t len,loff_t *off)
119
++{
120
++	return -EINVAL;
121
++}
122
++
123
++static ssize_t dev_write(struct file *flip,const char *buf,size_t len,loff_t *off)
124
++{
125
++	return -EINVAL;
126
++}
127
++
128
++static int dev_release(struct inode *inod,struct file *fil){
129
++	printk("KERN_ALERT device closed\n");
130
++	return 0;
131
++}
132
++
133
++static struct file_operations fops=
134
++{
135
++	.read=dev_read,
136
++	.write=dev_write,
137
++	.open=dev_open,
138
++	.release=dev_release,
139
++	.unlocked_ioctl=test_harness_ioctl,
140
++};
141
++
142
++int init_module(void)
143
++{
144
++	int err;
145
++
146
++	g_debug_level = TRACE_ALL;
147
++	err = crypt_init_module();
148
++	if (err)
149
++		return err;
150
++
151
++	user_data = kmalloc(user_data_size, GFP_KERNEL);
152
++	if (!user_data) {
153
++		crypt_cleanup_module();
154
++		return -ENOMEM;
155
++	}
156
++
157
++	err = register_chrdev(MAJOR_NUM,DEVICE_NAME,&fops);
158
++	if (err < 0 ){
159
++		kfree(user_data);
160
++		crypt_cleanup_module();
161
++		printk(KERN_ALERT "device registration failed. %d\n", err);
162
++	}
163
++
164
++	return err;
165
++}
166
++
167
++void cleanup_module(void)
168
++{
169
++	trace_debug(TRACE_FUNCTION, "Leaving FIPs Test\n");
170
++	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
171
++	kfree(user_data);
172
++	crypt_cleanup_module();
173
++}
174
++
175
++MODULE_LICENSE("GPL");
176
++MODULE_AUTHOR("VMware NSBU : Pravin <pshelar@vmware.com>");
177
+diff -Naur LKCM/fips_test.c LKCM.new/fips_test.c
178
+--- LKCM/fips_test.c	1970-01-01 00:00:00.000000000 +0000
179
+@@ -0,0 +1,830 @@
180
++#include <linux/kernel.h>
181
++#include <linux/module.h>
182
++#include <linux/init.h>
183
++#include <linux/fs.h>
184
++#include <asm/uaccess.h>
185
++#include <crypto/hash.h>
186
++#include <crypto/aes.h>
187
++#include <crypto/algapi.h>
188
++#include <crypto/skcipher.h>
189
++#include <linux/crypto.h>
190
++#include <linux/init.h>
191
++#include <linux/types.h>
192
++#include <linux/errno.h>
193
++#include <linux/err.h>
194
++#include <linux/crypto.h>
195
++#include <linux/ctype.h>
196
++#include <linux/vmalloc.h>
197
++#include <asm/byteorder.h>
198
++#include <linux/scatterlist.h>
199
++
200
++#include "test_harness_ioctl.h"
201
++#include "fips_test.h"
202
++
203
++#define DES_KEY_SIZE 8
204
++#define DIGEST_SIZE 512
205
++#define TEXT_SIZE (64 * (1024))
206
++
207
++#define VECTOR_TYPE_SIZE 20
208
++
209
++typedef struct crypt_test {
210
++    unsigned int algo;
211
++    unsigned int mask;
212
++    char vector_type[VECTOR_TYPE_SIZE];
213
++    int mode; //Encrypt=1 /Decrypt=2
214
++    int count;
215
++    int klen;
216
++    int data_tot_len;
217
++    int iv_len;
218
++    int rlen;
219
++    unsigned char *key;
220
++    unsigned char *iv;
221
++    unsigned char *hash_input;
222
++    unsigned char *hash_output;
223
++    struct scatterlist *sgin;
224
++} crypt_test_t;
225
++
226
++crypt_test_t *test_vector;
227
++static DEFINE_MUTEX(lock);
228
++static unsigned char txt_output[4096];
229
++
230
++static void to_ascii(char *out, int h)
231
++{
232
++    if (h <= 9)
233
++        *out = '0' + h;
234
++    else
235
++        *out = 'a' + (h - 10);
236
++    
237
++    printk("%c", *out);
238
++}
239
++
240
++static void hexdump_buf(char *alg, char *out, unsigned char *in, unsigned int ilen)
241
++{
242
++    int i, j = 0;
243
++    
244
++    printk("Result algo (%s): ", alg);
245
++    for (i = 0; i < ilen; i++) {
246
++        int u, l;
247
++        
248
++        u = in[i] >> 4;
249
++        l = in[i] & 0x0f;
250
++        
251
++        to_ascii(&out[j++], u);
252
++        to_ascii(&out[j++], l);
253
++    }
254
++    printk("\n");
255
++}
256
++
257
++static char char_to_hex(char ch)
258
++{
259
++    char ich = tolower(ch);
260
++    
261
++    if (ich >= 'a') {
262
++        return (ich - 'a' ) + 10;
263
++    } else {
264
++        return ch - '0';
265
++    }
266
++}
267
++
268
++static void hexdump(char *prefix, unsigned char *buf, unsigned int len)
269
++{
270
++    printk("pbs: klen %d\n", len);
271
++    print_hex_dump(KERN_EMERG, prefix, DUMP_PREFIX_OFFSET,
272
++                   16, 1,
273
++                   buf, len, false);
274
++}
275
++
276
++static void text_to_pack_bin(char *msg, unsigned char out[], unsigned char in[], int len)
277
++{
278
++    int i, j = 0;
279
++    
280
++    printk("%s len %d :- ", msg, len);
281
++    for (i = 0; i < len; i += 2) {
282
++        char p1, p2;
283
++        
284
++        p1 = char_to_hex(in[i]);
285
++        p2 = char_to_hex(in[i + 1]);
286
++        
287
++        out[j++] = (p1 << 4) | p2;
288
++        printk("%02x", out[j-1]);
289
++    }
290
++    printk("\n");
291
++}
292
++
293
++static struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask)
294
++{
295
++    return kzalloc(nents * sizeof(struct scatterlist), gfp_mask);
296
++}
297
++
298
++static void sg_kfree(struct scatterlist *sg, unsigned int nents)
299
++{
300
++    kfree(sg);
301
++}
302
++
303
++/* ----- */
304
++struct ft_crypt_result {
305
++    struct completion completion;
306
++    int err;
307
++};
308
++
309
++static void ft_crypt_complete(struct crypto_async_request *req, int err)
310
++{
311
++    struct ft_crypt_result *res = req->data;
312
++   
313
++    printk("pbs: async\n"); 
314
++    if (err == -EINPROGRESS)
315
++        return;
316
++    
317
++    res->err = err;
318
++    complete(&res->completion);
319
++}
320
++
321
++static void ft_result_init(struct ft_crypt_result *ft)
322
++{
323
++    memset(ft, 0, sizeof(*ft));
324
++    init_completion(&ft->completion);
325
++}
326
++
327
++int test_hash(crypt_test_t *test_vector)
328
++{
329
++    struct crypto_ahash *tfm = NULL;
330
++    struct ahash_request *req = NULL;
331
++    struct ft_crypt_result ft_result;
332
++    struct scatterlist sgin;
333
++    const char *algo;
334
++    int ret = -ENOMEM;
335
++    
336
++    tfm = crypto_alloc_ahash(test_vector->vector_type, test_vector->algo, test_vector-> mask);
337
++    if (IS_ERR(tfm)) {
338
++        printk(KERN_ERR "alg: cipher: Failed to load transform for "
339
++               "%s: %ld\n", "cbc(aes)", PTR_ERR(tfm));
340
++        return PTR_ERR(tfm);
341
++    }
342
++    
343
++    algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm));
344
++    if (algo) {
345
++        trace_debug( TRACE_DEBUG, "Algo = %s\n", algo );
346
++    } else {
347
++        printk("driver not available\n");
348
++        ret =  -EINVAL;
349
++        goto out;
350
++    }
351
++    
352
++    crypto_ahash_clear_flags(tfm, ~0);
353
++    if (test_vector->klen) {
354
++        ret = crypto_ahash_setkey(tfm, test_vector->key, test_vector->klen);
355
++        if (ret) {
356
++            printk("setting hash key err %d \n", ret);
357
++            goto out;
358
++        }
359
++    }
360
++    
361
++    ft_result_init(&ft_result);
362
++    req = ahash_request_alloc(tfm, GFP_KERNEL);
363
++    if (!req) {
364
++        ret = -ENOMEM;
365
++        printk("hash request alloc error \n");
366
++        goto out;
367
++    }
368
++    
369
++    ahash_request_set_tfm(req, tfm);
370
++    ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP |
371
++                               CRYPTO_TFM_REQ_MAY_BACKLOG,
372
++                               ft_crypt_complete, &ft_result);
373
++    
374
++    sg_init_one(&sgin, test_vector->hash_input, test_vector->data_tot_len);
375
++    
376
++    ahash_request_set_crypt(req, &sgin, test_vector->hash_output, test_vector->data_tot_len);
377
++    
378
++    ret = crypto_ahash_digest(req);
379
++    if (ret == -EINPROGRESS || ret == -EBUSY) {
380
++        ret = wait_for_completion_interruptible(&ft_result.completion);
381
++        if (!ret)
382
++            ret = ft_result.err;
383
++    }
384
++    
385
++    /*crypto_ahash_update() */
386
++    ahash_request_free(req);
387
++out:
388
++    crypto_free_ahash(tfm);
389
++    return ret;
390
++}
391
++
392
++int crypt_test_hash(int algo,
393
++                    unsigned char key[], int klen,
394
++                    unsigned char data[], int data_len,
395
++                    unsigned char out[], int *output_len)
396
++{
397
++    int ret, olen = 0;
398
++    
399
++    mutex_lock(&lock);
400
++    memset(test_vector, 0, sizeof (*test_vector));
401
++    
402
++    test_vector->hash_input = data;
403
++    test_vector->data_tot_len = data_len;
404
++    if (klen) {
405
++        test_vector->key = key;
406
++        test_vector->klen = klen;
407
++    }
408
++    test_vector->hash_output = out;
409
++    
410
++    switch (algo) {
411
++        case SHA1:
412
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
413
++            test_vector->mask = 0;
414
++            strcpy(test_vector->vector_type, "sha1");
415
++            olen = 20;
416
++            break;
417
++            
418
++        case SHA224:
419
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
420
++            test_vector->mask = 0;
421
++            strcpy(test_vector->vector_type, "sha224");
422
++            olen = 28;
423
++            
424
++            break;
425
++            
426
++        case SHA256:
427
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
428
++            test_vector->mask = 0;
429
++            strcpy(test_vector->vector_type, "sha256");
430
++            olen = 32;
431
++            break;
432
++            
433
++        case SHA384:
434
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
435
++            test_vector->mask = 0;
436
++            strcpy(test_vector->vector_type, "sha384");
437
++            olen = 48;
438
++            break;
439
++            
440
++        case SHA512:
441
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
442
++            test_vector->mask = 0;
443
++            strcpy(test_vector->vector_type, "sha512");
444
++            olen = 64;
445
++            break;
446
++            
447
++        case HMAC_SHA1:
448
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
449
++            test_vector->mask = 0;
450
++            strcpy(test_vector->vector_type, "hmac(sha1)");
451
++            olen = 20;
452
++            break;
453
++            
454
++        case HMAC_SHA224:
455
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
456
++            test_vector->mask = 0;
457
++            strcpy(test_vector->vector_type, "hmac(sha224)");
458
++            olen = 28;
459
++            break;
460
++            
461
++        case HMAC_SHA256:
462
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
463
++            test_vector->mask = 0;
464
++            strcpy(test_vector->vector_type, "hmac(sha256)");
465
++            olen = 32;
466
++            break;
467
++            
468
++        case HMAC_SHA384:
469
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
470
++            test_vector->mask = 0;
471
++            strcpy(test_vector->vector_type, "hmac(sha384)");
472
++            olen = 48;
473
++            break;
474
++            
475
++        case HMAC_SHA512:
476
++            test_vector->algo = CRYPTO_ALG_TYPE_SHASH;
477
++            test_vector->mask = 0;
478
++            strcpy(test_vector->vector_type, "hmac(sha512)");
479
++            olen = 64;
480
++            break;
481
++            
482
++        default:
483
++            printk("hash algo not supported");
484
++            ret = -EINVAL;
485
++            goto out;
486
++            break;
487
++    }
488
++    
489
++    ret = test_hash(test_vector);
490
++    if (!ret) {
491
++        *output_len = olen;
492
++    } else {
493
++        printk("test_hash (%s) err %d\n", test_vector->vector_type, ret);
494
++    }
495
++out:
496
++    mutex_unlock(&lock);
497
++    
498
++    return ret;
499
++}
500
++EXPORT_SYMBOL(crypt_test_hash);
501
++
502
++int crypt_test_hash_txt(int algo,
503
++                        unsigned char text_key[], int klen,
504
++                        unsigned char text_data[], int data_len,
505
++                        unsigned char text_out[], int *output_len)
506
++{
507
++    static unsigned char key[KEY_SIZE];
508
++    static unsigned char hash_input[TEXT_SIZE];
509
++    static unsigned char hash_output[DIGEST_SIZE];
510
++    int ret;
511
++    
512
++    if (data_len > (TEXT_SIZE*2))
513
++        return -E2BIG;
514
++    
515
++    text_to_pack_bin("hash input ", hash_input, text_data, data_len);
516
++    if (klen) {
517
++        text_to_pack_bin("hash key", key, text_key, klen);
518
++    }
519
++    ret = crypt_test_hash(algo, key, klen/2, hash_input, data_len/2,
520
++                          hash_output, output_len);
521
++    if (!ret) {
522
++        hexdump_buf(test_vector->vector_type, text_out, hash_output, *output_len);
523
++        *output_len = *output_len * 2;
524
++    } else {
525
++        printk("test_hash (%s) err %d\n", test_vector->vector_type, ret);
526
++    }
527
++    printk("---8<---\n");
528
++    return ret;
529
++}
530
++EXPORT_SYMBOL(crypt_test_hash_txt);
531
++
532
++static int test_sync_cipher(crypt_test_t *test_vector)
533
++{
534
++    struct crypto_cipher *tfm = NULL;
535
++    const char *algo;
536
++    void *data;
537
++    int ret = -ENOMEM;
538
++    int k;
539
++
540
++    tfm = crypto_alloc_cipher(test_vector->vector_type, test_vector->algo, test_vector->mask);
541
++    if (IS_ERR(tfm)) {
542
++        printk(KERN_ERR "sync-cipher: Failed to load transform for "
543
++               "%s type %x, mask %x: %ld\n", test_vector->vector_type,
544
++					     test_vector->algo,
545
++					     test_vector->mask,  PTR_ERR(tfm));
546
++        return PTR_ERR(tfm);
547
++    }
548
++    algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
549
++    if (algo) {
550
++        trace_debug( TRACE_DEBUG, "Algo = %s\n", algo );
551
++    } else {
552
++        printk("driver not available\n");
553
++        ret =  -EINVAL;
554
++        goto out;
555
++    }
556
++    
557
++    crypto_cipher_clear_flags(tfm, ~0);
558
++    ret = crypto_cipher_setkey(tfm, test_vector->key, test_vector->klen);
559
++    if (ret) {
560
++        hexdump("key: ", test_vector->key, test_vector->klen);
561
++        printk("setting cipher key err %d crt-flags %x\n", ret, crypto_cipher_get_flags(tfm));
562
++        goto out;
563
++    }
564
++    data = sg_virt(test_vector->sgin);
565
++    for (k = 0; k < test_vector->sgin->length;
566
++        k += crypto_cipher_blocksize(tfm)) {
567
++	if (test_vector->mode == ENCRYPT_MSG)
568
++           crypto_cipher_encrypt_one(tfm, data + k,
569
++				    data + k);
570
++	else
571
++	   crypto_cipher_decrypt_one(tfm, data + k,
572
++				    data + k);
573
++    }
574
++
575
++out:
576
++    crypto_free_cipher(tfm);
577
++    return ret;
578
++}
579
++
580
++static int test_sync_blk_cipher(crypt_test_t *test_vector)
581
++{
582
++    struct crypto_blkcipher *tfm = NULL;
583
++    struct blkcipher_desc desc;
584
++    const char *algo;
585
++    int ret = -ENOMEM;
586
++    
587
++    tfm = crypto_alloc_blkcipher(test_vector->vector_type, test_vector->algo, test_vector->mask);
588
++    if (IS_ERR(tfm)) {
589
++        printk(KERN_ERR "sync-blk-cipher: Failed to load transform for "
590
++               "%s: %ld\n", test_vector->vector_type, PTR_ERR(tfm));
591
++        return PTR_ERR(tfm);
592
++    }
593
++    
594
++    algo = crypto_tfm_alg_driver_name(crypto_blkcipher_tfm(tfm));
595
++    if (algo) {
596
++        trace_debug( TRACE_DEBUG, "Algo = %s\n", algo );
597
++    } else {
598
++        printk("driver not available\n");
599
++        ret =  -EINVAL;
600
++        goto out;
601
++    }
602
++
603
++    crypto_blkcipher_clear_flags(tfm, ~0);
604
++    ret = crypto_blkcipher_setkey(tfm, test_vector->key, test_vector->klen);
605
++    if (ret) {
606
++        hexdump("key: ", test_vector->key, test_vector->klen);
607
++        printk("setting cipher key err %d crt-flags %x\n", ret, crypto_blkcipher_get_flags(tfm));
608
++        goto out;
609
++    }
610
++    if (test_vector->iv_len) {
611
++       crypto_blkcipher_set_iv(tfm, test_vector->iv, test_vector->iv_len);
612
++    }
613
++
614
++    desc.tfm = tfm;
615
++    desc.flags = 0;
616
++ 
617
++    if (test_vector->mode == ENCRYPT_MSG)
618
++	ret = crypto_blkcipher_encrypt(&desc,
619
++				       test_vector->sgin, test_vector->sgin,
620
++				       test_vector->data_tot_len);
621
++    else
622
++	ret = crypto_blkcipher_decrypt(&desc,
623
++				       test_vector->sgin, test_vector->sgin,
624
++				       test_vector->data_tot_len);
625
++   
626
++out:
627
++    crypto_free_blkcipher(tfm);
628
++    return ret;
629
++}
630
++
631
++static int test_async_blk_cipher(crypt_test_t *test_vector)
632
++{
633
++    struct crypto_skcipher *tfm = NULL;
634
++    struct skcipher_request *req = NULL;
635
++    struct ft_crypt_result ft_result;
636
++    const char *algo;
637
++    int ret = -ENOMEM;
638
++    
639
++    tfm = crypto_alloc_skcipher(test_vector->vector_type, test_vector->algo, test_vector->mask);
640
++    if (IS_ERR(tfm)) {
641
++        printk(KERN_ERR "async-blk-cipher:: Failed to load transform for "
642
++               "%s: %ld\n", test_vector->vector_type, PTR_ERR(tfm));
643
++        return PTR_ERR(tfm);
644
++    }
645
++    
646
++    algo = crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm));
647
++    if (algo) {
648
++        trace_debug( TRACE_DEBUG, "Algo = %s\n", algo );
649
++    } else {
650
++        printk("driver not available\n");
651
++        ret =  -EINVAL;
652
++        goto out;
653
++    }
654
++    
655
++    crypto_skcipher_clear_flags(tfm, ~0);
656
++    ret = crypto_skcipher_setkey(tfm, test_vector->key, test_vector->klen);
657
++    if (ret) {
658
++        hexdump("key: ", test_vector->key, test_vector->klen);
659
++        printk("setting cipher key err %d crt-flags %x\n", ret, crypto_skcipher_get_flags(tfm));
660
++        goto out;
661
++    }
662
++    
663
++    ft_result_init(&ft_result);
664
++    req = skcipher_request_alloc(tfm, GFP_KERNEL);
665
++    if (!req) {
666
++        ret = -ENOMEM;
667
++        printk("cipher alloc error \n");
668
++        goto out;
669
++    }
670
++    
671
++    skcipher_request_set_tfm(req, tfm);
672
++    skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP |
673
++                                    CRYPTO_TFM_REQ_MAY_BACKLOG,
674
++                                    ft_crypt_complete, &ft_result);
675
++    
676
++    
677
++    skcipher_request_set_crypt(req, test_vector->sgin,
678
++                                 test_vector->sgin,
679
++                                 test_vector->data_tot_len,
680
++                                 test_vector->iv);
681
++    
682
++    if (test_vector->mode == ENCRYPT_MSG)
683
++        ret = crypto_skcipher_encrypt(req);
684
++    else {
685
++        ret = crypto_skcipher_decrypt(req);
686
++    }
687
++    if (ret == -EINPROGRESS || ret == -EBUSY) {
688
++        ret = wait_for_completion_interruptible(&ft_result.completion);
689
++        if (!ret)
690
++            ret = ft_result.err;
691
++    }
692
++    
693
++    skcipher_request_free(req);
694
++out:
695
++    crypto_free_skcipher(tfm);
696
++    return ret;
697
++}
698
++
699
++static int __crypt_test_cipher(int algo, int mode,
700
++                               unsigned char key[], int klen,
701
++                               unsigned char iv[], int iv_len,
702
++                               struct scatterlist *sgin, int tot_len)
703
++{
704
++    bool async = true;
705
++    int ret;
706
++    
707
++    mutex_lock(&lock);
708
++    memset(test_vector, 0, sizeof (*test_vector));
709
++    
710
++    test_vector->key = key;
711
++    test_vector->klen = klen;
712
++    test_vector->iv = iv;
713
++    test_vector->iv_len = iv_len;
714
++    test_vector->sgin = sgin;
715
++    test_vector->data_tot_len = tot_len;
716
++    test_vector->mode = mode;
717
++    
718
++    switch (algo) {
719
++        case AESCBC_NI:
720
++            test_vector->algo = CRYPTO_ALG_TYPE_BLKCIPHER;
721
++            test_vector->mask = 0;
722
++            strcpy(test_vector->vector_type, "cbc-aes-aesni");
723
++            break;
724
++
725
++        case AESCBC_GEN:
726
++	    if (0) {
727
++                test_vector->algo = CRYPTO_ALG_TYPE_CIPHER;
728
++                test_vector->mask = 0;
729
++                strcpy(test_vector->vector_type, "aes-generic");
730
++	    } else {
731
++                test_vector->algo = CRYPTO_ALG_TYPE_BLKCIPHER;
732
++                test_vector->mask = 0;
733
++                strcpy(test_vector->vector_type, "cbc(aes)");
734
++	        async = false;
735
++            }
736
++            break;
737
++
738
++        case AESECB_GEN:
739
++            test_vector->algo = CRYPTO_ALG_TYPE_BLKCIPHER;
740
++            test_vector->mask = 0;
741
++            strcpy(test_vector->vector_type, "ecb(aes)");
742
++	    async = false;
743
++            break;
744
++
745
++        case AESECB:
746
++            test_vector->algo = CRYPTO_ALG_TYPE_BLKCIPHER;
747
++            test_vector->mask = 0;
748
++            strcpy(test_vector->vector_type, "ecb-aes-aesni");
749
++            break;
750
++
751
++        case AESXTS:
752
++            test_vector->algo = CRYPTO_ALG_TYPE_BLKCIPHER;
753
++            test_vector->mask = 0;
754
++            strcpy(test_vector->vector_type, "xts-aes-aesni");
755
++            break;
756
++
757
++         case AESXTS_GEN:
758
++            test_vector->algo = CRYPTO_ALG_TYPE_BLKCIPHER;
759
++            test_vector->mask = 0;
760
++            strcpy(test_vector->vector_type, "xts(aes)");
761
++            async = false;
762
++            break;
763
++            
764
++        case TDES_CBC:
765
++            test_vector->algo = CRYPTO_ALG_TYPE_BLKCIPHER;
766
++            test_vector->mask = 0;
767
++            strcpy(test_vector->vector_type, "cbc(des3_ede)");
768
++            break;
769
++        case TDES_ECB:
770
++            test_vector->algo = CRYPTO_ALG_TYPE_BLKCIPHER;
771
++            test_vector->mask = 0;
772
++            strcpy(test_vector->vector_type, "ecb(des3_ede)");
773
++            break;
774
++            
775
++        default:
776
++            printk("cipher algo not supported");
777
++            ret = -EINVAL;
778
++            goto out;
779
++            break;
780
++    }
781
++    if (test_vector->algo == CRYPTO_ALG_TYPE_CIPHER)
782
++	    ret = test_sync_cipher(test_vector);
783
++    else {
784
++	if (async)
785
++	    ret = test_async_blk_cipher(test_vector);
786
++	else
787
++	    ret = test_sync_blk_cipher(test_vector);
788
++    }
789
++
790
++out:
791
++    mutex_unlock(&lock);
792
++    return ret;
793
++}
794
++
795
++/* this functions can handle large buffer of input data.
796
++ * the buffers can be passed as parameter sgin in form of
797
++ * scatter gather list.
798
++ * idealy each scatter gather entry should be of size upto 8KB.
799
++ * last parameter 'sg_size' is number of entries in the sgin array.
800
++ * Encrypted msg is returned in same buffer. so the sgin
801
++ * buffer should be writable buffer. */
802
++
803
++int crypt_test_cipher_txt_sg(int algo, int mode,
804
++                             unsigned char text_key[], int klen,
805
++                             unsigned char text_iv[], int iv_len,
806
++                             struct scatterlist *sgin, int sg_size)
807
++{
808
++    struct scatterlist *sg_data;
809
++    static unsigned char key[KEY_SIZE];
810
++    static unsigned char iv[MAX_IVLEN];
811
++    int tot_len = 0;
812
++    int i, err;
813
++    
814
++    sg_data = sg_kmalloc(sg_size, GFP_KERNEL);
815
++    if (!sg_data)
816
++        return -ENOMEM;
817
++    
818
++    for (i = 0; i < sg_size; i++) {
819
++        void *buf;
820
++        
821
++        buf = kmalloc(sgin[i].length, GFP_KERNEL);
822
++        if (!buf) {
823
++            err = -ENOMEM;
824
++            goto err;
825
++        }
826
++        text_to_pack_bin("cipher input ", buf, sg_virt(&sgin[i]), sgin[i].length);
827
++        
828
++        sg_set_buf(&sg_data[i], buf, sgin[i].length / 2);
829
++        tot_len += sg_data[i].length;
830
++    }
831
++    text_to_pack_bin("cipher key", key, text_key, klen);
832
++    text_to_pack_bin("cipher iv", iv, text_iv, iv_len);
833
++    
834
++    err = __crypt_test_cipher(algo, mode, key, klen / 2, iv, iv_len / 2,
835
++                              sg_data, tot_len);
836
++    if (!err) {
837
++        for (i = 0; i < sg_size; i++) {
838
++            hexdump_buf(test_vector->vector_type, sg_virt(&sgin[i]), sg_virt(&sg_data[i]), sg_data[i].length);
839
++            kfree(sg_virt(&sg_data[i]));
840
++        }
841
++    } else
842
++        printk("cipher (%s) err %d\n", test_vector->vector_type, err);
843
++    printk("---8<---\n");
844
++    sg_kfree(sg_data, sg_size);
845
++    return err;
846
++err:
847
++    for (; i >= 0; i--)
848
++        kfree(sg_virt(&sg_data[i]));
849
++    sg_kfree(sg_data, sg_size);
850
++    
851
++    return err;
852
++}
853
++
854
++int crypt_test_cipher_txt(int algo, int mode,
855
++                          unsigned char test_key[], int klen,
856
++                          unsigned char test_iv[], int iv_len,
857
++                          unsigned char test_data[], int data_len)
858
++{
859
++    struct scatterlist sgin;
860
++    
861
++    sg_init_one(&sgin, test_data, data_len);
862
++    
863
++    return crypt_test_cipher_txt_sg(algo, mode,
864
++                                    test_key, klen, test_iv, iv_len,
865
++                                    &sgin, 1);
866
++}
867
++EXPORT_SYMBOL(crypt_test_cipher_txt);
868
++
869
++int crypt_test_cipher(int algo, int mode,
870
++                      unsigned char key[], int klen,
871
++                      unsigned char iv[], int iv_len,
872
++                      unsigned char data[], int data_len)
873
++{
874
++    struct scatterlist sgin;
875
++    int err;
876
++    
877
++    sg_init_one(&sgin, data, data_len);
878
++    
879
++    err = __crypt_test_cipher(algo, mode, key, klen, iv, iv_len,
880
++                              &sgin, data_len);
881
++    if (err)
882
++        printk("cipher (%s) err %d\n", test_vector->vector_type, err);
883
++    return err;
884
++}
885
++EXPORT_SYMBOL(crypt_test_cipher);
886
++
887
++static int module_self_test(void)
888
++{
889
++    int olen;
890
++
891
++    if (1) {
892
++        {
893
++            unsigned char key[] = "00000000000000000000000000000000";
894
++            unsigned char iv[] = "00000000000000000000000000000000";
895
++            unsigned char input[] = "9798c4640bad75c7c3227db910174e72";
896
++            
897
++            
898
++            crypt_test_cipher_txt(AESCBC_GEN, ENCRYPT_MSG,
899
++                                  key, strlen(key), iv, strlen(iv),
900
++                                  input, strlen(input));
901
++        }
902
++        {
903
++            unsigned char key[] = "00000000000000000000000000000000";
904
++            unsigned char iv[] = "00000000000000000000000000000000";
905
++            unsigned char input[] = "9798c4640bad75c7c3227db910174e72";
906
++            
907
++            
908
++            crypt_test_cipher_txt(AESCBC_NI, ENCRYPT_MSG,
909
++                                  key, strlen(key), iv, strlen(iv),
910
++                                  input, strlen(input));
911
++        }
912
++	return 0;
913
++        {
914
++            unsigned char key[] = "00000000000000000000000000000000";
915
++            unsigned char iv[] = "00000000000000000000000000000000";
916
++            unsigned char input[] = "f34481ec3cc627bacd5dc3fb08f273e6";
917
++            
918
++            
919
++            crypt_test_cipher_txt(AESECB, ENCRYPT_MSG,
920
++                                  key, strlen(key), iv, strlen(iv),
921
++                                  input, strlen(input));
922
++        }
923
++         {
924
++            unsigned char key[] = "00000000000000000000000000000000";
925
++            unsigned char iv[] = "00000000000000000000000000000000";
926
++            unsigned char input[] = "f34481ec3cc627bacd5dc3fb08f273e6";
927
++            
928
++            
929
++            crypt_test_cipher_txt(AESECB_GEN, ENCRYPT_MSG,
930
++                                  key, strlen(key), iv, strlen(iv),
931
++                                  input, strlen(input));
932
++        }
933
++         {
934
++            unsigned char key[] = "d9ea889d65357515e4137012457468b9fda0a4ff3efd66de889418e07b426336";
935
++            unsigned char iv[] = "fc504a6e5249451ed0b8d62e2bdd07e1";
936
++            unsigned char input[] = "2b4dcfa944a32a75d27a47e06e4f650a";
937
++            
938
++            crypt_test_cipher_txt(AESXTS, ENCRYPT_MSG,
939
++                                  key, strlen(key), iv, strlen(iv),
940
++                                  input, strlen(input));
941
++        }              
942
++        {
943
++            unsigned char key[] = "39f7e4a8a0584d2e0d39fe252866129abfe5d92c52335ea3b6f053bd808e2df22ff669ab27336cf31bf83a15df41157f36956f97004b391667e67eaf445c3a9e";
944
++            unsigned char iv[] = "99a0ee1bc920eafd02925561be00cd13";
945
++            unsigned char input[] = "cf786eec36fddc5295dd478dfb16dd321b27812fe2b13d7bb4a9ec56cd70f5f3";
946
++            
947
++            crypt_test_cipher_txt(AESXTS, ENCRYPT_MSG,
948
++                                  key, strlen(key), iv, strlen(iv),
949
++                                  input, strlen(input));
950
++        }
951
++         {
952
++            unsigned char key[] = "d9ea889d65357515e4137012457468b9fda0a4ff3efd66de889418e07b426336";
953
++            unsigned char iv[] = "fc504a6e5249451ed0b8d62e2bdd07e1";
954
++            unsigned char input[] = "2b4dcfa944a32a75d27a47e06e4f650a";
955
++            
956
++            crypt_test_cipher_txt(AESXTS_GEN, ENCRYPT_MSG,
957
++                                  key, strlen(key), iv, strlen(iv),
958
++                                  input, strlen(input));
959
++        }
960
++        {
961
++            unsigned char key[] = "0101010101010101";
962
++            unsigned char iv[] = "0000000000000000";
963
++            unsigned char input1[] = "95f8a5e5dd31d900";
964
++            unsigned char input2[] = "95f8a5e5dd31d900";
965
++            unsigned char keya[] = "f46ea8f4491fdfbcaee6e69e345ba24ff46ea8f4491fdfbc";
966
++            unsigned char inputa[] = "8d980ce5ef807297";
967
++            
968
++            crypt_test_cipher_txt(TDES_CBC, ENCRYPT_MSG,
969
++                                  key, strlen(key), iv, strlen(iv),
970
++                                  input1, strlen(input1));
971
++            crypt_test_cipher_txt(TDES_ECB, ENCRYPT_MSG,
972
++                                  key, strlen(key), iv, strlen(iv),
973
++                                  input2, strlen(input2));
974
++            crypt_test_cipher_txt(TDES_ECB, DECRYPT_MSG,
975
++                                  keya, strlen(keya), iv, strlen(iv),
976
++                                  inputa, strlen(inputa));
977
++            
978
++        }
979
++    }
980
++    return 0;
981
++    crypt_test_hash_txt(SHA1,   NULL, 0, "6b86636e", 8, txt_output, &olen);
982
++    crypt_test_hash_txt(SHA256, NULL, 0, "7f9c783f05d1c1e5ce86b22612", 26, txt_output, &olen);
983
++    
984
++    {
985
++        char key[] = "d8490f5eb74d5ab458c61d212e278e55";
986
++        char msg[] = "fba41998f50163dff6be2acab152619252c92dd8bf0147811e19a3c497274f815b299dd5e53f84eb8017441509a8491bf62352d39726d2f19c339621d862a9534452755647652aa9342d648e1521085fa7956e25a5e9c6674900b44011f33eb4bf07e844a3dd1dc01ce9d15d5d2565086d07cbf971b0ea8a2e66444aca44d64d";
987
++        int klen = strlen(key);
988
++        int mlen = strlen(msg);
989
++        
990
++        crypt_test_hash_txt(HMAC_SHA256, key, klen, msg, mlen, txt_output, &olen);
991
++    }
992
++    return 0;
993
++}
994
++
995
++int crypt_init_module(void)
996
++{
997
++    test_vector = kmalloc(sizeof (*test_vector), GFP_KERNEL | __GFP_NOWARN);
998
++    if (!test_vector)
999
++        return -ENOMEM;
1000
++
1001
++    if (0) 
1002
++        module_self_test();
1003
++    return 0;
1004
++}
1005
++
1006
++void crypt_cleanup_module(void)
1007
++{
1008
++    kfree(test_vector);
1009
++}
1010
+diff -Naur LKCM/fips_test.h LKCM.new/fips_test.h
1011
+--- LKCM/fips_test.h	1970-01-01 00:00:00.000000000 +0000
1012
+@@ -0,0 +1,18 @@
1013
++#ifndef CRYPT_TEST_MODULE
1014
++#define CRYPT_TEST_MODULE
1015
++
1016
++int crypt_init_module(void);
1017
++void crypt_cleanup_module(void);
1018
++
1019
++int crypt_test_cipher(int algo, int mode,
1020
++			unsigned char test_key[], int klen,
1021
++			unsigned char test_iv[], int iv_len,
1022
++			unsigned char test_data[], int data_len);
1023
++
1024
++
1025
++int crypt_test_hash(int algo,
1026
++		      unsigned char test_key[], int klen,
1027
++		      unsigned char test_data[], int data_len,
1028
++		      unsigned char test_out[], int *output_len);
1029
++
1030
++#endif
1031
+diff -Naur LKCM/Makefile LKCM.new/Makefile
1032
+--- LKCM/Makefile	1970-01-01 00:00:00.000000000 +0000
1033
+@@ -0,0 +1,3 @@
1034
++obj-m += fips_lkcm.o
1035
++fips_lkcm-objs :=  drv_fips_test.o fips_test.o
1036
++
1037
+diff -Naur LKCM/test_harness_ioctl.h LKCM.new/test_harness_ioctl.h
1038
+--- LKCM/test_harness_ioctl.h	1970-01-01 00:00:00.000000000 +0000
1039
+@@ -0,0 +1,104 @@
1040
++//
1041
++//  test_harness_ioctl.h
1042
++//
1043
++//  Header file for communication between user-apps and LKCMtest driver module
1044
++//
1045
++//  VMware 9/14/16.
1046
++//
1047
++#ifndef __TEST_HARNESS_H
1048
++#define __TEST_HARNESS_H
1049
++#include <linux/ioctl.h>
1050
++
1051
++#define DEVICE_NAME "lkcm_dev"
1052
++#define MAJOR_NUM 90
1053
++#define USER_LOG_FILE "/tmp/lkcm_log.txt"
1054
++
1055
++#define ENCRYPT_MSG 1
1056
++#define DECRYPT_MSG 2
1057
++
1058
++
1059
++// Crypto Algo Types
1060
++enum {
1061
++	AESCBC_GEN,
1062
++	AESCBC_NI,
1063
++	AESECB,
1064
++	AESECB_GEN,
1065
++	AESXTS,
1066
++	AESXTS_GEN,
1067
++	TDES_CBC,
1068
++	TDES_ECB,
1069
++        HMAC_SHA1,
1070
++        HMAC_SHA224,
1071
++        HMAC_SHA256,
1072
++        HMAC_SHA384,
1073
++        HMAC_SHA512,
1074
++	SHA1,
1075
++	SHA224,
1076
++	SHA256,
1077
++	SHA384,
1078
++	SHA512,
1079
++};
1080
++
1081
++#define KEY_SIZE 256
1082
++#define MAX_IVLEN 32
1083
++#define MAX_DATA_LEN (1024 * 1024 * 10)
1084
++
1085
++typedef struct test_data_v1 {
1086
++	int algo;
1087
++	int mode;
1088
++	int klen;
1089
++	int iv_len;
1090
++	int data_len;
1091
++	int status;
1092
++	unsigned char test_key[KEY_SIZE];
1093
++	unsigned char test_iv[MAX_IVLEN];
1094
++	unsigned char test_data[];
1095
++} test_data_v1_t;
1096
++
1097
++static inline int test_data_v1_sz(struct test_data_v1 *t)
1098
++{
1099
++	return sizeof (*t) + t->data_len;
1100
++}
1101
++
1102
++#define IOCTL_SET_VECTOR _IOWR(MAJOR_NUM, 1, test_data_v1_t*)
1103
++#define QUERY_CLEAR_VALUE _IOWR(MAJOR_NUM, 2)
1104
++#define QUERY_SET_VALUE _IOW(MAJOR_NUM, 3, int *)
1105
++
1106
++
1107
++extern int g_debug_level;
1108
++
1109
++#define TRACE_ERR 0x00000001
1110
++#define TRACE_DEBUG 0x00000002
1111
++#define TRACE_FUNCTION 0x00000004
1112
++#define TRACE_ALL (TRACE_ERR|TRACE_DEBUG|TRACE_FUNCTION)
1113
++
1114
++#ifdef __KERNEL__
1115
++#define trace_debug(level, fmt, args...) \
1116
++{\
1117
++	if ((level & g_debug_level)) {\
1118
++		printk( "[%s:%d] " fmt, __FUNCTION__, __LINE__, ##args); \
1119
++	}\
1120
++}
1121
++#else
1122
++#define trace_debug(level, fmt, args...) \
1123
++{ \
1124
++	FILE * fp = NULL;\
1125
++	if ((level & g_debug_level)) {\
1126
++		struct stat file_stat;\
1127
++		stat(USER_LOG_FILE, &file_stat );\
1128
++		if ( file_stat.st_size > 10000 ) { \
1129
++			fp = fopen(USER_LOG_FILE, "w+"); }\
1130
++		else {\
1131
++			fp = fopen(USER_LOG_FILE, "a+"); }\
1132
++		if ( fp ){\
1133
++			printf("[%s:%d] " fmt, __FUNCTION__, __LINE__, ##args); \
1134
++			fprintf(fp,"[%s:%d] " fmt, __FUNCTION__, __LINE__, ##args); \
1135
++			fclose(fp);\
1136
++		}\
1137
++	}\
1138
++}
1139
++#endif
1140
++
1141
++
1142
++
1143
++#endif
... ...
@@ -2,7 +2,7 @@
2 2
 Summary:        Kernel
3 3
 Name:           linux-secure
4 4
 Version:        4.9.13
5
-Release:        2%{?dist}
5
+Release:        3%{?dist}
6 6
 License:        GPLv2
7 7
 URL:            http://www.kernel.org/
8 8
 Group:          System Environment/Kernel
... ...
@@ -30,6 +30,8 @@ Patch12:        x86-vmware-sta.patch
30 30
 Patch13:        0001-NOWRITEEXEC-and-PAX-features-MPROTECT-EMUTRAMP.patch
31 31
 Patch14:        0002-Added-rap_plugin.patch
32 32
 Patch15:        0003-Added-PAX_RANDKSTACK.patch
33
+# NSX requirements
34
+Patch16:        LKCM.patch
33 35
 BuildRequires:  bc
34 36
 BuildRequires:  kbd
35 37
 BuildRequires:  kmod
... ...
@@ -111,6 +113,9 @@ EOF
111 111
 %patch13 -p1
112 112
 %patch14 -p1
113 113
 %patch15 -p1
114
+pushd ..
115
+%patch16 -p0
116
+popd
114 117
 
115 118
 %build
116 119
 # patch vmw_balloon driver
... ...
@@ -121,6 +126,11 @@ cp %{SOURCE1} .config
121 121
 sed -i 's/CONFIG_LOCALVERSION="-secure"/CONFIG_LOCALVERSION="-%{release}-secure"/' .config
122 122
 make LC_ALL= oldconfig
123 123
 make VERBOSE=1 KBUILD_BUILD_VERSION="1-photon" KBUILD_BUILD_HOST="photon" ARCH="x86_64" %{?_smp_mflags}
124
+# build LKCM module
125
+bldroot=`pwd`
126
+pushd ../LKCM
127
+make -C $bldroot M=`pwd` modules
128
+popd
124 129
 
125 130
 %define __modules_install_post \
126 131
 for MODULE in `find %{buildroot}/lib/modules/%{uname_r} -name *.ko` ; do \
... ...
@@ -146,6 +156,11 @@ install -vdm 755 %{buildroot}%{_defaultdocdir}/linux-%{uname_r}
146 146
 install -vdm 755 %{buildroot}/etc/modprobe.d
147 147
 install -vdm 755 %{buildroot}/usr/src/linux-headers-%{uname_r}
148 148
 make INSTALL_MOD_PATH=%{buildroot} modules_install
149
+# install LKCM module
150
+bldroot=`pwd`
151
+pushd ../LKCM
152
+make -C $bldroot M=`pwd` INSTALL_MOD_PATH=%{buildroot} modules_install
153
+popd
149 154
 cp -v arch/x86/boot/bzImage    %{buildroot}/boot/vmlinuz-%{uname_r}
150 155
 cp -v System.map        %{buildroot}/boot/System.map-%{uname_r}
151 156
 cp -v .config            %{buildroot}/boot/config-%{uname_r}
... ...
@@ -201,6 +216,8 @@ ln -sf linux-%{uname_r}.cfg /boot/photon.cfg
201 201
 /usr/src/linux-headers-%{uname_r}
202 202
 
203 203
 %changelog
204
+*   Tue Mar 21 2017 Alexey Makhalov <amakhalov@vmware.com> 4.9.13-3
205
+-   Added LKCM module
204 206
 *   Mon Mar 6 2017 Alexey Makhalov <amakhalov@vmware.com> 4.9.13-2
205 207
 -   .config: NSX requirements for crypto and netfilter
206 208
 *   Tue Feb 28 2017 Alexey Makhalov <amakhalov@vmware.com> 4.9.13-1