08f1904fb60849ad1c4ce9afaa58bb70f61174d9
[platform/upstream/ima-evm-utils.git] / src / evmctl.c
1 /*
2  * evm-utils - IMA/EVM support utilities
3  *
4  * Copyright (C) 2011 Nokia Corporation
5  * Copyright (C) 2011 Intel Corporation
6  *
7  * Authors:
8  * Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
9  *                 <dmitry.kasatkin@intel.com>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * version 2.1 as published by the Free Software Foundation.
14  *
15  * This library is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  *
25  * File: evmctl.c
26  *       IMA/EVM control program
27  */
28
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <attr/xattr.h>
40 #include <getopt.h>
41 #include <signal.h>
42 #include <keyutils.h>
43 #include <asm/byteorder.h>
44 #include <syslog.h>
45 #include <attr/xattr.h>
46 #include <dirent.h>
47
48 #include <openssl/sha.h>
49 #include <openssl/rsa.h>
50 #include <openssl/pem.h>
51 #include <openssl/hmac.h>
52 #include <openssl/engine.h>
53 #include <openssl/evp.h>
54 #include <openssl/err.h>
55
56 #define USE_FPRINTF
57
58 #ifdef USE_FPRINTF
59 #define do_log(level, fmt, args...)     if (level <= verbose) fprintf(stderr, fmt, ##args)
60 #define do_log_dump(level, p, len)      if (level <= verbose) do_dump(stderr, p, len)
61 #else
62 #define do_log(level, fmt, args...)     syslog(level, fmt, ##args)
63 #define do_log_dump(p, len)
64 #endif
65
66 #ifdef DEBUG
67 #define log_debug(fmt, args...)         do_log(LOG_DEBUG, "%s:%d " fmt, __func__ , __LINE__ , ##args)
68 #define log_debug_dump(p, len)          do_log_dump(LOG_DEBUG, p, len)
69 #else
70 #define log_debug(fmt, args...)
71 #define log_debug_dump(p, len)
72 #endif
73
74 #define log_dump(p, len)                do_log_dump(LOG_INFO, p, len)
75 #define log_info(fmt, args...)          do_log(LOG_INFO, fmt, ##args)
76 #define log_err(fmt, args...)           do_log(LOG_ERR, fmt, ##args)
77 #define log_errno(fmt, args...)         do_log(LOG_ERR, fmt ": %s (%d)\n", ##args, strerror(errno), errno)
78
79 #define DATA_SIZE       4096
80 #define SHA1_HASH_LEN   20
81
82 #define EXT2_IOC_GETVERSION     _IOR('v', 1, long)
83 #define EXT34_IOC_GETVERSION    _IOR('f', 3, long)
84
85 #define FS_IOC_GETFLAGS         _IOR('f', 1, long)
86 #define FS_IOC_SETFLAGS         _IOW('f', 2, long)
87 #define FS_IOC32_GETFLAGS       _IOR('f', 1, int)
88 #define FS_IOC32_SETFLAGS       _IOW('f', 2, int)
89
90 struct h_misc {
91         unsigned long ino;
92         uint32_t generation;
93         uid_t uid;
94         gid_t gid;
95         unsigned short mode;
96 } hmac_misc;
97
98 enum pubkey_algo {
99         PUBKEY_ALGO_RSA,
100         PUBKEY_ALGO_MAX,
101 };
102
103 enum digest_algo {
104         DIGEST_ALGO_SHA1,
105         DIGEST_ALGO_SHA256,
106         DIGEST_ALGO_MAX
107 };
108
109 struct pubkey_hdr {
110         uint8_t         version;        /* key format version */
111         time_t          timestamp;      /* key made, always 0 for now */
112         uint8_t         algo;
113         uint8_t         nmpi;
114         char            mpi[0];
115 } __attribute__ ((packed));
116
117
118 struct signature_hdr {
119         uint8_t         version;        /* signature format version */
120         time_t          timestamp;      /* signature made */
121         uint8_t         algo;
122         uint8_t         hash;
123         uint8_t         keyid[8];
124         uint8_t         nmpi;
125         char            mpi[0];
126 } __attribute__ ((packed));
127
128
129 static char *evm_config_xattrnames[] = {
130         "security.selinux",
131         "security.SMACK64",
132         "security.ima",
133         "security.capability",
134         NULL
135 };
136
137 struct command {
138         char    *name;
139         int     (*func)(struct command *cmd);
140         int     cmd;
141         char    *arg;
142         char    *msg;   /* extra info message */
143 };
144
145 static int              verbose = LOG_INFO - 1;
146 static int              g_argc;
147 static char             **g_argv;
148 static int              set_xattr = 1;
149 static int              digest = 0;
150 static int              digsig = 0;
151 static char             *hash_algo = "sha1";
152 static int              binkey = 0;
153 static char             *keypass;
154
155 extern struct command   cmds[];
156 static void print_usage(struct command *cmd);
157
158 static void do_dump(FILE *fp, const void *ptr, int len)
159 {
160         int     i;
161         uint8_t *data = (uint8_t *)ptr;
162
163         for (i = 0; i < len; i++) {
164                 fprintf(fp, "%02x", data[i]);
165         }
166         fprintf(fp, "\n");
167 }
168
169 static void dump(const void *ptr, int len)
170 {
171         do_dump(stdout, ptr, len);
172 }
173
174 static inline int get_filesize(const char *filename)
175 {
176         struct stat stats;
177         /*  Need to know the file length */
178         stat(filename, &stats);
179         return (int) stats.st_size;
180 }
181
182 static inline int get_fdsize(int fd)
183 {
184         struct stat stats;
185         /*  Need to know the file length */
186         fstat(fd, &stats);
187         return (int) stats.st_size;
188 }
189
190 static int bin2file(const char *file, const char *ext, const unsigned char *data, int len)
191 {
192         FILE *fp;
193         char name[strlen(file) + (ext ? strlen(ext) : 0) + 2];
194         int err;
195         
196         if (ext)
197                 sprintf(name, "%s.%s", file, ext);
198         else
199                 sprintf(name, "%s", file);
200
201         log_info("Writing to %s\n", name);
202
203         fp = fopen(name, "w");
204         if (!fp) {
205                 log_errno("Unable to open %s for writing", name);
206                 return -1;
207         }
208         err = fwrite(data, len, 1, fp);
209         fclose(fp);
210         return err;
211 }
212
213 static char *file2bin(const char *file, int *size)
214 {
215         FILE *fp;
216         int len;
217         char *data;
218                 
219         len = get_filesize(file);
220         fp = fopen(file, "r");
221         if (!fp) {
222                 log_errno("Unable to open %s", file);
223                 return NULL;
224         }
225         data = malloc(len);
226         if (!fread(data, len, 1, fp))
227                 len = 0;
228         fclose(fp);
229         
230         *size = len;
231         return data;    
232 }
233
234 /*
235  * Create binary key representation suitable for kernel
236  */
237 static int key2bin(RSA *key, unsigned char *pub)
238 {
239         int len, b, offset = 0;
240         struct pubkey_hdr *pkh = (struct pubkey_hdr *)pub;
241
242         /* add key header */
243         pkh->version = 1;
244         pkh->timestamp = 0;     /* PEM has no timestamp?? */
245         pkh->algo = PUBKEY_ALGO_RSA;
246         pkh->nmpi = 2;
247         
248         offset += sizeof(*pkh);
249         
250         // MPIs
251         len = BN_num_bytes(key->n);
252         b = BN_num_bits(key->n);
253         pub[offset++] = b >> 8;
254         pub[offset++] = b & 0xff;
255         BN_bn2bin(key->n, &pub[offset]);
256         offset += len;
257         
258         len = BN_num_bytes(key->e);
259         b = BN_num_bits(key->e);
260         pub[offset++] = b >> 8;
261         pub[offset++] = b & 0xff;
262         BN_bn2bin(key->e, &pub[offset]);
263         offset += len;
264         
265         return offset;
266 }
267
268 static int read_key(const char *inkey, unsigned char *pub)
269 {
270         FILE *fp;
271         RSA *key = NULL, *key1;
272         int len;
273
274         fp = fopen(inkey, "r");
275         if (!fp) {
276                 log_errno("read key failed from file %s", inkey);
277                 return -1;
278         }
279
280         key1 = PEM_read_RSA_PUBKEY(fp, &key, NULL, NULL);
281         fclose(fp);
282         if (!key1) {
283                 log_errno("PEM_read_RSA_PUBKEY() failed");
284                 return -1;
285         }
286         
287         len = key2bin(key, pub);
288         
289         RSA_free(key);
290         
291         return len;
292 }
293
294
295 static void calc_keyid(uint8_t *keyid, char *str, const unsigned char *pkey, int len)
296 {
297         uint8_t sha1[SHA_DIGEST_LENGTH];
298         uint64_t id;
299         
300         log_debug("pkey:\n");
301         log_debug_dump(pkey, len);
302         SHA1(pkey, len, sha1);  
303         
304         //sha1[12 - 19] is exactly keyid from gpg file
305         memcpy(keyid, sha1 + 12, 8);
306         log_debug("keyid:\n");
307         log_debug_dump(keyid, 8);
308         
309         id = __be64_to_cpup((__be64 *)keyid);
310         sprintf(str, "%llX", (unsigned long long)id);
311         log_info("keyid: %s\n", str);   
312 }
313
314 static int sign_hash(const unsigned char *hash, int size, const char *keyfile, unsigned char *sig)
315 {
316         int err, len;
317         SHA_CTX ctx;
318         unsigned char pub[1024];
319         RSA *key = NULL, *key1;
320         FILE *fp;
321         char name[20];
322         unsigned char sighash[20];
323         struct signature_hdr *hdr = (struct signature_hdr *)sig;
324         uint16_t *blen;
325         
326         log_info("hash: ");
327         log_dump(hash, size);
328         
329         fp = fopen(keyfile, "r");       
330         if (!fp) {
331                 log_errno("Unable to open keyfile %s", keyfile);
332                 return -1;
333         }
334         key1 = PEM_read_RSAPrivateKey(fp, &key, NULL, keypass);
335         fclose(fp);
336         if (!key1) {
337                 log_errno("RSAPrivateKey() failed");
338                 return -1;
339         }
340
341         /* now create a new hash */
342         hdr->version = 1;
343         time(&hdr->timestamp);
344         hdr->algo = PUBKEY_ALGO_RSA;
345         hdr->hash = DIGEST_ALGO_SHA1;
346         
347         len = key2bin(key, pub);
348         calc_keyid(hdr->keyid, name, pub, len);
349         
350         hdr->nmpi = 1;
351         
352         SHA1_Init(&ctx);
353         SHA1_Update(&ctx, hash, size);
354         SHA1_Update(&ctx, hdr, sizeof(*hdr));
355         SHA1_Final(sighash, &ctx);
356         log_info("sighash: ");
357         log_dump(sighash, sizeof(sighash));
358
359         err = RSA_private_encrypt(sizeof(sighash), sighash, sig + sizeof(*hdr) + 2, key, RSA_PKCS1_PADDING);
360         RSA_free(key);
361         if (err < 0) {
362                 log_errno("RSA_private_encrypt() failed: %d", err);
363                 return -1;
364         }
365
366         len = err;
367         
368         /* we add bit length of the signature to make it gnupg compatible */
369         blen = (uint16_t *)(sig + sizeof(*hdr));
370         *blen = __cpu_to_be16(len << 3);
371         len += sizeof(*hdr) + 2;
372         log_info("evm/ima signature: %d bytes\n", len);
373         if (!set_xattr || verbose >= LOG_INFO)
374                 dump(sig, len);
375
376         return len;     
377 }
378
379 static int calc_evm_hash(const char *file, const char *keyfile, unsigned char *hash)
380 {
381         struct stat st;
382         int fd, err;
383         uint32_t generation;
384         EVP_MD_CTX ctx;
385         const EVP_MD *md;
386         unsigned int mdlen;
387         char **xattrname;
388         char xattr_value[1024];
389         
390         fd = open(file, 0);
391         if (fd < 0) {
392                 log_errno("Unable to open %s", file);
393                 return -1;
394         }
395         
396         if (fstat(fd, &st)) {
397                 log_errno("fstat() failed");
398                 return -1;
399         }
400         
401         if (ioctl(fd, EXT34_IOC_GETVERSION, &generation)) {
402                 log_errno("ioctl() failed");
403                 return -1;
404         }
405         
406         close(fd);
407         
408         log_info("generation: %u\n", generation);
409
410         md = EVP_get_digestbyname("sha1");
411         if (!md) {
412                 log_errno("EVP_get_digestbyname() failed");
413                 return -1;
414         }
415
416         err = EVP_DigestInit(&ctx, md);
417         if (!err) {
418                 log_errno("EVP_DigestInit() failed");
419                 return -1;
420         }
421
422         for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
423                 err = getxattr(file, *xattrname, xattr_value, sizeof(xattr_value));
424                 if (err < 0) {
425                         log_info("no attr: %s\n", *xattrname);
426                         continue;
427                 }
428                 //log_debug("name: %s, value: %s, size: %d\n", *xattrname, xattr_value, err);
429                 log_info("name: %s, size: %d\n", *xattrname, err);
430                 log_debug_dump(xattr_value, err);
431                 err = EVP_DigestUpdate(&ctx, xattr_value, err);
432                 if (!err) {
433                         log_errno("EVP_DigestUpdate() failed");
434                         return -1;
435                 }
436         }
437
438         memset(&hmac_misc, 0, sizeof(hmac_misc));
439         hmac_misc.ino = st.st_ino;
440         hmac_misc.generation = generation;
441         hmac_misc.uid = st.st_uid;
442         hmac_misc.gid = st.st_gid;
443         hmac_misc.mode = st.st_mode;
444         
445         err = EVP_DigestUpdate(&ctx, (const unsigned char*)&hmac_misc, sizeof(hmac_misc));
446         if (!err) {
447                 log_errno("EVP_DigestUpdate() failed");
448                 return -1;
449         }
450         err = EVP_DigestFinal(&ctx, hash, &mdlen);
451         if (!err) {
452                 log_errno("EVP_DigestFinal() failed");
453                 return -1;
454         }
455         
456         return 0;
457 }
458
459 static int sign_evm(const char *file, const char *key)
460 {
461         unsigned char hash[20];
462         unsigned char sig[1024] = "\x03";
463         int err;
464
465         calc_evm_hash(file, key, hash);
466         
467         err = sign_hash(hash, sizeof(hash), key, sig + 1);
468         if (err < 0)
469                 return err;
470         
471         if (set_xattr) {
472                 err = setxattr(file, "security.evm", sig, err + 1, 0);
473                 if (err < 0) {
474                         log_errno("setxattr failed: %s", file);
475                         return err;
476                 }
477         }
478         
479         return 0;
480 }
481
482 static int calc_file_hash(const char *file, uint8_t *hash)
483 {
484         EVP_MD_CTX ctx;
485         const EVP_MD *md;
486         uint8_t *data;
487         int err, size, bs = DATA_SIZE;
488         size_t len;
489         unsigned int mdlen;
490         FILE *fp;
491
492         data = malloc(bs);
493         if (!data) {
494                 log_errno("malloc failed");
495                 return -1;
496         }
497                 
498         fp = fopen(file, "r");
499         if (!fp) {
500                 log_errno("Unable to open %s", file);
501                 return -1;
502         }
503         
504         md = EVP_get_digestbyname(hash_algo);
505         if (!md) {
506                 log_errno("EVP_get_digestbyname() failed");
507                 return -1;
508         }
509
510         err = EVP_DigestInit(&ctx, md);
511         if (!err) {
512                 log_errno("EVP_DigestInit() failed");
513                 return -1;
514         }
515
516         for (size = get_fdsize(fileno(fp)); size; size -= len) {
517                 len = MIN(size, bs);
518                 err = fread(data, len, 1, fp);
519                 if (!err) {
520                         if (ferror(fp)) {
521                                 log_errno("fread() error\n");
522                                 return -1;
523                         }
524                         break;
525                 }
526                 err = EVP_DigestUpdate(&ctx, data, len);
527                 if (!err) {
528                         log_errno("EVP_DigestUpdate() failed");
529                         return -1;
530                 }
531         }
532
533         err = EVP_DigestFinal(&ctx, hash, &mdlen);
534         if (!err) {
535                 log_errno("EVP_DigestFinal() failed");
536                 return -1;
537         }
538
539         fclose(fp);
540         
541         free(data);
542         
543         return mdlen;
544 }
545
546 struct dirent_list {
547         struct dirent_list *next;
548         struct dirent de;
549 };
550
551 static int calc_dir_hash(const char *file, uint8_t *hash)
552 {
553         EVP_MD_CTX ctx;
554         const EVP_MD *md;
555         int err;
556         unsigned int mdlen;
557         struct dirent *de;
558         DIR *dir;
559         struct dirent_list *head = NULL, *pos, *prev, *cur;
560         uint64_t ino;
561
562         dir = opendir(file);
563         if (!dir) {
564                 log_errno("Unable to open %s", file);
565                 return -1;
566         }
567         
568         md = EVP_get_digestbyname(hash_algo);
569         if (!md) {
570                 log_errno("EVP_get_digestbyname() failed");
571                 return -1;
572         }
573
574         err = EVP_DigestInit(&ctx, md);
575         if (!err) {
576                 log_errno("EVP_DigestInit() failed");
577                 return -1;
578         }
579
580         while ((de = readdir(dir))) {
581                 //printf("entry: ino: %lu, %s\n", de->d_ino, de->d_name);
582                 for (prev = NULL, pos = head; pos; prev = pos, pos = pos->next) {
583                         if (de->d_ino < pos->de.d_ino)
584                                 break;
585                 }
586                 cur = malloc(sizeof(*cur));
587                 cur->de = *de;
588                 cur->next = pos;
589                 if (!head || !prev)
590                         head = cur;
591                 else
592                         prev->next = cur;
593         }
594         
595         for (cur = head; cur; cur = pos) {
596                 pos = cur->next;
597                 ino = cur->de.d_ino;
598                 log_debug("entry: ino: %llu, %s\n", (unsigned long long)ino, cur->de.d_name);
599                 err = EVP_DigestUpdate(&ctx, cur->de.d_name, strlen(cur->de.d_name));
600                 if (!err) {
601                         log_errno("EVP_DigestUpdate() failed");
602                         return -1;
603                 }
604                 err = EVP_DigestUpdate(&ctx, &ino, sizeof(ino));
605                 if (!err) {
606                         log_errno("EVP_DigestUpdate() failed");
607                         return -1;
608                 }
609                 free(cur);
610         }
611                 
612         err = EVP_DigestFinal(&ctx, hash, &mdlen);
613         if (!err) {
614                 log_errno("EVP_DigestFinal() failed");
615                 return -1;
616         }
617
618         closedir(dir);
619         
620         return mdlen;
621 }
622
623 static int hash_ima(const char *file)
624 {
625         unsigned char hash[65] = "\x01";// MAX hash size + 1
626         int err;
627         struct stat st;
628
629         /*  Need to know the file length */
630         err = stat(file, &st);
631         if (err < 0) {
632                 log_errno("stat() failed");
633                 return err;
634         }
635
636         if (S_ISDIR(st.st_mode))
637                 err = calc_dir_hash(file, hash + 1);
638         else
639                 err = calc_file_hash(file, hash + 1);
640         if (err < 0)
641                 return err;
642         
643         if (verbose >= LOG_INFO)
644                 log_info("hash: ");
645
646         if (!set_xattr || verbose >= LOG_INFO)
647                 dump(hash, err + 1);
648
649         if (set_xattr) {
650                 err = setxattr(file, "security.ima", hash, err + 1, 0);
651                 if (err < 0) {
652                         log_errno("setxattr failed: %s", file);
653                         return err;
654                 }
655         }
656         
657         return 0;
658 }
659
660 static int cmd_hash_ima(struct command *cmd)
661 {
662         char *file = g_argv[optind++];
663
664         if (!file) {
665                 log_err("Parameters missing\n");
666                 print_usage(cmd);
667                 return 1;
668         }
669         
670         return hash_ima(file);
671 }
672
673 static int sign_ima(const char *file, const char *key)
674 {
675         unsigned char hash[64];
676         unsigned char sig[1024] = "\x03";
677         int err;
678         
679         err = calc_file_hash(file, hash);
680         if (err < 0)
681                 return err;
682         
683         err = sign_hash(hash, err, key, sig + 1);
684         if (err < 0)
685                 return err;
686         
687         if (set_xattr) {
688                 err = setxattr(file, "security.ima", sig, err + 1, 0);
689                 if (err < 0) {
690                         log_errno("setxattr failed: %s", file);
691                         return err;
692                 }
693         }
694         
695         return 0;
696 }
697
698 static int cmd_sign_ima(struct command *cmd)
699 {
700         char *key, *file = g_argv[optind++];
701         
702         if (!file) {
703                 log_err("Parameters missing\n");
704                 print_usage(cmd);
705                 return 1;
706         }
707         
708         key = g_argv[optind++];
709         if (!key)
710                 key = "/etc/keys/privkey_evm.pem";
711         
712         return sign_ima(file, key);
713         
714 }
715
716 static int cmd_sign_evm(struct command *cmd)
717 {
718         char *key, *file = g_argv[optind++];
719         int err;
720         
721         if (!file) {
722                 log_err("Parameters missing\n");
723                 print_usage(cmd);
724                 return 1;
725         }
726         
727         key = g_argv[optind++];
728         if (!key)
729                 key = "/etc/keys/privkey_evm.pem";
730         
731         if (digsig) {
732                 err = sign_ima(file, key);
733                 if (err)
734                         return err;
735         }
736         
737         if (digest) {
738                 err = hash_ima(file);
739                 if (err)
740                         return err;
741         }
742         
743         return sign_evm(file, key);
744 }
745
746 static int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int siglen, const char *keyfile)
747 {
748         int err, len;
749         SHA_CTX ctx;
750         unsigned char out[1024];
751         RSA *key = NULL, *key1;
752         FILE *fp;
753         unsigned char sighash[20];
754         struct signature_hdr *hdr = (struct signature_hdr *)sig;
755         
756         log_info("hash: ");
757         log_dump(hash, size);
758         
759         fp = fopen(keyfile, "r");       
760         if (!fp) {
761                 log_errno("Unable to open keyfile %s", keyfile);
762                 return -1;
763         }
764         key1 = PEM_read_RSA_PUBKEY(fp, &key, NULL, NULL);
765         fclose(fp);
766         if (!key1) {
767                 log_errno("PEM_read_RSA_PUBKEY() failed");
768                 return -1;
769         }
770
771         SHA1_Init(&ctx);
772         SHA1_Update(&ctx, hash, size);
773         SHA1_Update(&ctx, hdr, sizeof(*hdr));
774         SHA1_Final(sighash, &ctx);
775         log_info("sighash: ");
776         log_dump(sighash, sizeof(sighash));
777
778         err = RSA_public_decrypt(siglen - sizeof(*hdr) - 2, sig + sizeof(*hdr) + 2, out, key, RSA_PKCS1_PADDING);
779         RSA_free(key);
780         if (err < 0) {
781                 log_errno("RSA_public_decrypt() failed: %d", err);
782                 return -1;
783         }
784
785         len = err;
786         
787         if (len != sizeof(sighash) || memcmp(out, sighash, len) != 0) {
788                 log_errno("Verification failed: %d", err);
789                 return -1;
790         } else {
791                 //log_info("Verification is OK\n");
792                 printf("Verification is OK\n");
793         }
794         
795         return 0;
796 }
797
798 static int verify_evm(const char *file, const char *key)
799 {
800         unsigned char hash[20];
801         unsigned char sig[1024];
802         int err;
803
804         calc_evm_hash(file, key, hash);
805         
806         err = getxattr(file, "security.evm", sig, sizeof(sig));
807         if (err < 0) {
808                 log_errno("getxattr failed");
809                 return err;
810         }
811         
812         if (sig[0] != 0x03) {
813                 log_errno("security.evm has not signature");
814                 return err;
815         }
816         
817         return verify_hash(hash, sizeof(hash), sig + 1, err - 1, key);
818 }
819
820 static int cmd_verify_evm(struct command *cmd)
821 {
822         char *key, *file = g_argv[optind++];
823         
824         if (!file) {
825                 log_err("Parameters missing\n");
826                 print_usage(cmd);
827                 return 1;
828         }
829         
830         key = g_argv[optind++];
831         if (!key)
832                 key = "/etc/keys/pubkey_evm.pem";
833         
834         return verify_evm(file, key);
835 }
836
837 static int cmd_convert(struct command *cmd)
838 {
839         char *inkey, *outkey = NULL;
840         unsigned char pub[1024];
841         char name[20];
842         int len;
843         uint8_t keyid[8];
844         
845         inkey = g_argv[optind++];
846         if (!inkey)
847                 inkey = "/etc/keys/pubkey_evm.pem";
848         else
849                 outkey = g_argv[optind++];
850                 
851         if (!outkey)
852                 outkey = "pubkey_evm.bin";
853
854         log_info("Convert public key %s to %s\n", inkey, outkey);       
855
856         len = read_key(inkey, pub);
857         if (len < 0)
858                 return -1;
859         
860         calc_keyid(keyid, name, pub, len);
861         
862         bin2file(outkey, name, pub, len);
863
864         return 0;
865 }
866
867 static int cmd_import_bin(struct command *cmd)
868 {
869         int len;
870         char *inkey, *ring = NULL;
871         char *key, name[20];
872         key_serial_t id;
873         uint8_t keyid[8];
874         
875         inkey = g_argv[optind++];
876         if (!inkey)
877                 inkey = "/etc/keys/pubkey_evm.bin";
878         else
879                 ring = g_argv[optind++];
880                 
881         if (!ring)
882                 id = KEY_SPEC_USER_KEYRING;
883         else
884                 id = atoi(ring);
885
886         key = file2bin(inkey, &len);
887         if (!key)
888                 return -1;
889         
890         calc_keyid(keyid, name, (unsigned char *)key, len);
891
892         log_info("Importing public key %s from file %s into keyring %d\n", name, inkey, id);
893         
894         id = add_key("user", name, key, len, id);
895         if (id < 0) {
896                 log_errno("add_key failed");
897                 return -1;
898         }
899
900         log_info("keyid: %d\n", id);
901         printf("%d\n", id);
902         
903         free(key);
904         
905         return 0;
906 }
907
908 static int cmd_import(struct command *cmd)
909 {
910         char *inkey, *ring = NULL;
911         unsigned char key[1024];
912         int id, len;
913         char name[20];
914         uint8_t keyid[8];
915
916         if (binkey)
917                 return cmd_import_bin(cmd);
918         
919         inkey = g_argv[optind++];
920         if (!inkey)
921                 inkey = "/etc/keys/pubkey_evm.pem";
922         else
923                 ring = g_argv[optind++];
924                 
925         if (!ring)
926                 id = KEY_SPEC_USER_KEYRING;
927         else
928                 id = atoi(ring);
929
930         len = read_key(inkey, key);
931         if (len < 0)
932                 return -1;
933         
934         calc_keyid(keyid, name, key, len);
935         
936         log_info("Importing public key %s from file %s into keyring %d\n", name, inkey, id);
937         
938         id = add_key("user", name, key, len, id);
939         if (id < 0) {
940                 log_errno("add_key failed");
941                 return -1;
942         }
943
944         log_info("keyid: %d\n", id);
945         printf("%d\n", id);
946         
947         return 0;
948 }
949
950 #define MAX_KEY_SIZE 128
951
952 static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *hash)
953 {
954         struct stat st;
955         int fd, err;
956         uint32_t generation;
957         HMAC_CTX ctx;
958         unsigned int mdlen;
959         char **xattrname;
960         unsigned char xattr_value[1024];
961         char *key;
962         int keylen;
963         unsigned char evmkey[MAX_KEY_SIZE];
964         
965         key = file2bin(keyfile, &keylen);
966         if (!key) {
967                 log_errno("Unable to read a key: %s\n", keyfile);
968                 return -1;
969         }
970         
971         if (keylen > sizeof(evmkey)) {
972                 log_errno("key is too long\n");
973                 return -1;
974         }
975
976         /* EVM key is 128 bytes */
977         memcpy(evmkey, key, keylen);
978         memset(evmkey + keylen, 0, sizeof(evmkey) - keylen);
979         
980         fd = open(file, 0);
981         if (fd < 0) {
982                 log_errno("Unable to open %s", file);
983                 return -1;
984         }
985         
986         if (fstat(fd, &st)) {
987                 log_errno("fstat() failed");
988                 return -1;
989         }
990         
991         if (ioctl(fd, EXT34_IOC_GETVERSION, &generation)) {
992                 log_errno("ioctl() failed");
993                 return -1;
994         }
995         
996         close(fd);
997         
998         log_info("generation: %u\n", generation);
999
1000         HMAC_Init(&ctx, evmkey, sizeof(evmkey), EVP_sha1());
1001
1002         for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
1003                 err = getxattr(file, *xattrname, xattr_value, sizeof(xattr_value));
1004                 if (err < 0) {
1005                         log_info("no attr: %s\n", *xattrname);
1006                         continue;
1007                 }
1008                 //log_debug("name: %s, value: %s, size: %d\n", *xattrname, xattr_value, err);
1009                 log_info("name: %s, size: %d\n", *xattrname, err);
1010                 log_debug_dump(xattr_value, err);
1011                 HMAC_Update(&ctx, xattr_value, err);
1012         }
1013
1014         memset(&hmac_misc, 0, sizeof(hmac_misc));
1015         hmac_misc.ino = st.st_ino;
1016         hmac_misc.generation = generation;
1017         hmac_misc.uid = st.st_uid;
1018         hmac_misc.gid = st.st_gid;
1019         hmac_misc.mode = st.st_mode;
1020         
1021         HMAC_Update(&ctx, (const unsigned char*)&hmac_misc, sizeof(hmac_misc));
1022         HMAC_Final(&ctx, hash, &mdlen);
1023         HMAC_CTX_cleanup(&ctx);
1024         
1025         free(key);
1026
1027         return 0;
1028 }
1029
1030 static int hmac_evm(const char *file, const char *key)
1031 {
1032         unsigned char hash[20];
1033         unsigned char sig[1024] = "\x02";
1034         int err;
1035
1036         calc_evm_hmac(file, key, hash);
1037         
1038         log_info("hmac: ");
1039         log_dump(hash, sizeof(hash));
1040         memcpy(sig + 1, hash, sizeof(hash));
1041         err = sizeof(hash);
1042         
1043         if (set_xattr) {
1044                 err = setxattr(file, "security.evm", sig, err + 1, 0);
1045                 if (err < 0) {
1046                         log_errno("setxattr failed: %s", file);
1047                         return err;
1048                 }
1049         }
1050         
1051         return 0;
1052 }
1053
1054 static int cmd_hmac_evm(struct command *cmd)
1055 {
1056         char *key, *file = g_argv[optind++];
1057         int err;
1058         
1059         if (!file) {
1060                 log_err("Parameters missing\n");
1061                 print_usage(cmd);
1062                 return 1;
1063         }
1064         
1065         key = g_argv[optind++];
1066         if (!key)
1067                 key = "/etc/keys/privkey_evm.pem";
1068         
1069         if (digsig) {
1070                 err = sign_ima(file, key);
1071                 if (err)
1072                         return err;
1073         }
1074         
1075         if (digest) {
1076                 err = hash_ima(file);
1077                 if (err)
1078                         return err;
1079         }
1080         
1081         return hmac_evm(file, "/etc/keys/evm-key-plain");
1082 }
1083
1084 static void print_usage(struct command *cmd)
1085 {
1086         printf("usage: %s %s\n", cmd->name, cmd->arg ? cmd->arg : "");
1087 }
1088
1089 static void print_full_usage(struct command *cmd)
1090 {
1091         if (cmd->name)
1092                 printf("usage: %s %s\n", cmd->name, cmd->arg ? cmd->arg : "");
1093         if (cmd->msg)
1094                 printf("description:\n%s", cmd->msg);
1095
1096 }
1097
1098 static int print_command_usage(struct command *cmds, char *command)
1099 {
1100         struct command  *cmd;
1101
1102         for (cmd = cmds; cmd->name; cmd++) {
1103                 if (strcmp(cmd->name, command) == 0) {
1104                         print_full_usage(cmd);
1105                         return 0;
1106                 }
1107         }
1108         printf("invalid command: %s\n", command);
1109         return  1;
1110 }
1111
1112 static void print_all_usage(struct command *cmds)
1113 {
1114         struct command  *cmd;
1115         
1116         for (cmd = cmds; cmd->name; cmd++) {
1117                 if (cmd->arg)
1118                         printf("%s %s\n", cmd->name, cmd->arg);
1119                 else if (cmd->msg)
1120                         printf("%s", cmd->msg);
1121         }
1122 }
1123
1124 static int call_command(struct command *cmds, char *command)
1125 {
1126         struct command  *cmd;
1127         
1128         for (cmd = cmds; cmd->name; cmd++) {
1129                 if (strcasecmp(cmd->name, command) == 0)
1130                         return cmd->func(cmd);
1131         }
1132         printf("Invalid command: %s\n", command);
1133         return -1;
1134 }
1135
1136 static int cmd_help(struct command *cmd)
1137 {
1138         if (!g_argv[optind]) {
1139                 print_usage(cmd);
1140                 return 0;
1141         } else
1142                 return print_command_usage(cmds, g_argv[optind]);
1143 }
1144
1145 static void usage(void)
1146 {
1147         printf("Usage: evmctl <command> [parameters..]\n");
1148
1149         print_all_usage(cmds);
1150 }
1151
1152 struct command cmds[] = {
1153         {"help", cmd_help, 0, "<command>"},
1154         {"import", cmd_import, 0, "[--bin] inkey keyring", "Import public key (PEM/bin) into the keyring.\n" },
1155         {"convert", cmd_convert, 0, "inkey outkey", "Convert PEM public key into IMA/EVM kernel friendly format.\n" },
1156         {"sign", cmd_sign_evm, 0, "[--imahash | --imasig ] file [key]", "Sign file metadata.\n" },
1157         {"verify", cmd_verify_evm, 0, "file", "Verify EVM signature (for debugging).\n" },
1158         {"ima_sign", cmd_sign_ima, 0, "file [key]", "Sign file content.\n" },
1159         {"ima_hash", cmd_hash_ima, 0, "file", "Hash file content.\n" },
1160         {"hmac", cmd_hmac_evm, 0, "[--imahash | --imasig ] file [key]", "Sign file metadata with HMAC (for debugging).\n" },
1161         {0, 0, 0, NULL}
1162 };
1163
1164 static struct option  opts[] = {
1165         {"help", 0, 0, 'h'},
1166         {"inkey", 1, 0, 'k'},
1167         {"imasig", 0, 0, 's'},
1168         {"imahash", 0, 0, 'd'},
1169         {"hashalgo", 1, 0, 'a'},
1170         {"bin", 0, 0, 'b'},
1171         {"pass", 1, 0, 'p'},
1172         {}
1173
1174 };
1175
1176 int main(int argc, char *argv[])
1177 {
1178         int err = 0, c, lind;
1179
1180         g_argv = argv;
1181         g_argc = argc;
1182
1183         while (1) {
1184                 c = getopt_long(argc, argv, "hk:vnsda:bp:", opts, &lind);
1185                 if (c == -1)
1186                         break;
1187                         
1188                 switch (c) {
1189                 case 'h':
1190                         usage();
1191                         exit(0);
1192                         break;
1193                 case 'k':
1194                         printf("inkey: %s\n", optarg);
1195                         break;
1196                 case 'v':
1197                         verbose++;
1198                         break;
1199                 case 'd':
1200                         digest = 1;
1201                         break;
1202                 case 's':
1203                         digsig = 1;
1204                         break;
1205                 case 'n':
1206                         set_xattr = 0; // do not set Extended Attributes... just print signature
1207                         break;
1208                 case 'a':
1209                         hash_algo = optarg;
1210                         break;
1211                 case 'b':
1212                         binkey = 1;
1213                         break;
1214                 case 'p':
1215                         keypass = optarg;
1216                         break;
1217                 case '?':
1218                         exit(1);
1219                         break;
1220                 default:
1221                         log_err("getopt() returned: %d (%c)\n", c, c);
1222                 }
1223         }
1224
1225         OpenSSL_add_all_algorithms();
1226         ERR_load_crypto_strings();
1227
1228         if (argv[optind] == NULL)
1229                 usage();
1230         else
1231                 err = call_command(cmds, argv[optind++]);
1232
1233         if (err)
1234                 log_err("error: %s\n", ERR_error_string(ERR_get_error(), NULL));
1235
1236         ERR_free_strings();
1237         EVP_cleanup();
1238
1239         return err;
1240 }