source: libabac/abac_key.c @ ba6027a

mei_rt2mei_rt2_fix_1
Last change on this file since ba6027a was ba6027a, checked in by Mei <mei@…>, 12 years ago

1) modified code all around to add support for encrypted private key for

ID credential

2) add new abac_key_t structure (abac_key.c)
3) add new keycheck option to creddy
4) add 2 new test suites

  • Property mode set to 100644
File size: 6.4 KB
Line 
1
2/**
3**  abac_key.c
4**  holding a private_key
5**/
6
7// include the GNU extension of asprintf
8#define _GNU_SOURCE
9
10#include <stdio.h>
11#include <time.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <unistd.h>
15#include <fcntl.h>
16#include <sys/mman.h>
17#include <assert.h>
18
19#include "abac_internal.h"
20#include "abac_util.h"
21
22extern chunk_t abac_get_potato_cb(int try, char *name);
23
24static int debug=0;
25//
26// abac_key object
27//
28// keyblob and potato are 'cleaned' explicitly
29struct _abac_key_t {
30    chunk_t keyblob;
31    char* filename;
32    chunk_t potato; // you know what, just as a hint
33};
34
35/****************************************************************/
36//
37// Helper functions below
38//
39void print_abac_key(char *msg, abac_key_t *ptr)
40{
41    printf("===============\n");
42    if(ptr->keyblob.len !=0) {
43        printf("[%s]ptr:loc(%d)\n",msg,(int) ptr->keyblob.ptr);
44        printf("[%s]len:(%d)\n",msg,ptr->keyblob.len);
45        printf("[%s]strlen:(%d)\n",msg,strlen(ptr->keyblob.ptr));
46        if(strlen(ptr->keyblob.ptr) != ptr->keyblob.len) 
47            printf("BAD, did not match\b\n");
48    }
49    if(ptr->filename)
50        printf("[%s]filename:(%s)\n",msg,ptr->filename);
51    if(ptr->potato.len !=0) {
52        printf("[%s]pptr:loc(%d)\n",msg,(int)ptr->potato.ptr);
53        printf("[%s]plen:(%d)\n",msg,ptr->potato.len);
54        printf("[%s]pstrlen:(%d)\n",msg,strlen(ptr->potato.ptr));
55    }
56    printf("===============\n");
57}
58
59static private_key_t *_load_privkey_chunk(chunk_t chunk)
60{
61    if(debug) { 
62        printf("_load_privkey_chunk, ptr loc(%d):(%d)\n",
63                             (int) chunk.ptr, chunk.len);
64    }
65    private_key_t *key = lib->creds->create(lib->creds,
66        CRED_PRIVATE_KEY, KEY_RSA,
67        BUILD_BLOB_PEM, chunk,
68        BUILD_END
69    );
70    return key;
71}
72
73static private_key_t *_load_enc_privkey_chunk(chunk_t chunk, chunk_t potato)
74{
75    if(debug) { 
76        printf("_load_enc_privkey_chunk, ptr loc(%d):(%d)\n",
77                                      (int) chunk.ptr, chunk.len);
78    }
79    mem_cred_t *mem;
80    shared_key_t *shared;
81
82    mem = mem_cred_create();
83    lib->credmgr->add_set(lib->credmgr, &mem->set);
84    shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, chunk_clone(potato));
85    mem->add_shared(mem, shared, NULL);
86
87    // load signer key
88    private_key_t *key =_load_privkey_chunk(chunk);
89
90    lib->credmgr->remove_set(lib->credmgr, &mem->set);
91    mem->destroy(mem);
92
93    return key;
94}
95
96private_key_t *abac_key_private_key(abac_key_t *ptr)
97{
98    private_key_t *prv=NULL;
99    if(ptr->potato.len !=0) {
100        prv=_load_enc_privkey_chunk(ptr->keyblob, ptr->potato);
101        } else  {
102            if(debug)
103                print_abac_key("abac_key_private_key",ptr);
104            prv=_load_privkey_chunk(ptr->keyblob);
105/* try to use callback to retrieve the potato token */
106            if(prv == NULL && ptr->filename) {
107               chunk_t pp=abac_get_potato_cb(2, ptr->filename);
108               if(pp.len != 0) {
109                   prv=_load_enc_privkey_chunk(ptr->keyblob, pp);
110                   ptr->potato=pp;
111               }
112            }
113    }
114
115    return prv;
116}
117
118chunk_t abac_key_load_privkey_file(char *filename)
119{
120    chunk_t blob=chunk_empty;
121    struct stat sb;
122    void *addr;
123    int fd;
124
125    if(!file_exist(filename)) 
126        return chunk_empty;
127
128    fd = open(filename, O_RDONLY);
129    if (fd == -1) {
130        printf("warning, can not open the %s\n",filename);
131        return blob;
132    }   
133
134    if (fstat(fd, &sb) == -1) {
135        printf("warning, key file(%s) is empty\n",filename);
136        close(fd);
137        return blob;
138    }
139
140    addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
141    if (addr == MAP_FAILED) {
142        printf("warning, mapping '%s' failed\n", filename);
143        close(fd);
144        return blob;
145    }
146
147    blob.ptr=strndup(addr, sb.st_size);
148    blob.len=sb.st_size;
149
150    munmap(addr, sb.st_size);
151    close(fd);
152    return blob;
153}
154
155/**
156 * Generate a private key.
157 */
158static chunk_t _generate_keyblob(void) {
159    private_key_t *key=NULL;
160    chunk_t encoding=chunk_empty;
161    libabac_init();
162
163    // generate the key
164    key = lib->creds->create(
165        lib->creds,
166        CRED_PRIVATE_KEY, KEY_RSA,
167        BUILD_KEY_SIZE, 2048,
168        BUILD_END
169    );
170    if (key == NULL)
171        errx(1, "Key generation failed");
172
173    int ret = key->get_encoding(key, PRIVKEY_PEM, &encoding);
174    if (!ret) {
175        DESTROY_IF(key);
176        errx(1, "Couldn't encode private key");
177    }
178    /* HACK.. it seems encoding ptr's string is often longer than
179       encoding len */
180    char *new_ptr=strndup(encoding.ptr,encoding.len);
181    free(encoding.ptr);
182    encoding.ptr=new_ptr;
183    DESTROY_IF(key);
184    return encoding;
185}
186
187/**
188 * Write the private key to a file.
189 * Returns false if there's no private key loaded
190 */
191int abac_key_write_privkey(abac_key_t *key, FILE *out) {
192
193    fwrite(key->keyblob.ptr, key->keyblob.len, 1, out);
194    return 1;
195}
196
197/**
198 * Get a PEM-encoded chunk representing the private key
199 */
200chunk_t abac_key_chunk(abac_key_t *ptr) {
201    return ptr->keyblob;
202}
203
204/*****************************************************************/
205/*  load with a filename                                         */
206/*  load with a filename and potato                               */
207/*  load with a chunk blob                                       */
208/*  load with a chunk blob and a potato                           */
209/*****************************************************************/
210abac_key_t *abac_key_file_new(char *filename, chunk_t potato)
211{
212    abac_key_t *ptr = abac_xmalloc(sizeof(abac_key_t));
213    if(potato.len != 0)
214        ptr->potato=potato;
215        else ptr->potato=chunk_empty;
216    ptr->keyblob=abac_key_load_privkey_file(filename);
217    ptr->filename=abac_xstrdup(filename);
218    return ptr;
219}
220
221/* just use the keyblob, did not reallocate */
222abac_key_t *abac_key_chunk_new(chunk_t keyblob, chunk_t potato)
223{
224    abac_key_t *ptr = abac_xmalloc(sizeof(abac_key_t));
225    if(potato.len != 0)
226        ptr->potato=potato;
227        else ptr->potato=chunk_empty;
228    ptr->keyblob=keyblob;
229    ptr->filename=NULL;
230    return ptr;
231}
232
233abac_key_t *abac_key_generate()
234{
235    abac_key_t *ptr = abac_xmalloc(sizeof(abac_key_t));
236    ptr->potato=chunk_empty;
237    ptr->filename=NULL;
238    ptr->keyblob=_generate_keyblob();
239    return ptr;
240}
241
242void abac_key_free(abac_key_t *ptr)
243{
244    if(ptr->potato.len != 0)
245        chunk_clear(&ptr->potato);
246    if(debug) {
247         printf("FREEEEE abac_key loc(%d)\n",(int)ptr->keyblob.ptr);
248    }
249    chunk_clear(&ptr->keyblob);
250    free(ptr);
251}
Note: See TracBrowser for help on using the repository browser.