/** ** abac_key.c ** holding a private_key **/ // include the GNU extension of asprintf #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "abac_internal.h" #include "abac_util.h" extern chunk_t abac_get_potato_cb(int try, char *name); static int debug=0; // // abac_key object // // keyblob and potato are 'cleaned' explicitly struct _abac_key_t { chunk_t keyblob; char* filename; chunk_t potato; // you know what, just as a hint }; /****************************************************************/ // // Helper functions below // void print_abac_key(char *msg, abac_key_t *ptr) { printf("===============\n"); if(ptr->keyblob.len !=0) { printf("[%s]ptr:loc(%d)\n",msg,(int) ptr->keyblob.ptr); printf("[%s]len:(%d)\n",msg,ptr->keyblob.len); printf("[%s]strlen:(%d)\n",msg,strlen(ptr->keyblob.ptr)); if(strlen(ptr->keyblob.ptr) != ptr->keyblob.len) printf("BAD, did not match\b\n"); } if(ptr->filename) printf("[%s]filename:(%s)\n",msg,ptr->filename); if(ptr->potato.len !=0) { printf("[%s]pptr:loc(%d)\n",msg,(int)ptr->potato.ptr); printf("[%s]plen:(%d)\n",msg,ptr->potato.len); printf("[%s]pstrlen:(%d)\n",msg,strlen(ptr->potato.ptr)); } printf("===============\n"); } static private_key_t *_load_privkey_chunk(chunk_t chunk) { if(debug) { printf("_load_privkey_chunk, ptr loc(%d):(%d)\n", (int) chunk.ptr, chunk.len); } private_key_t *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, BUILD_BLOB_PEM, chunk, BUILD_END ); return key; } static private_key_t *_load_enc_privkey_chunk(chunk_t chunk, chunk_t potato) { if(debug) { printf("_load_enc_privkey_chunk, ptr loc(%d):(%d)\n", (int) chunk.ptr, chunk.len); } mem_cred_t *mem; shared_key_t *shared; mem = mem_cred_create(); lib->credmgr->add_set(lib->credmgr, &mem->set); shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, chunk_clone(potato)); mem->add_shared(mem, shared, NULL); // load signer key private_key_t *key =_load_privkey_chunk(chunk); lib->credmgr->remove_set(lib->credmgr, &mem->set); mem->destroy(mem); return key; } private_key_t *abac_key_private_key(abac_key_t *ptr) { private_key_t *prv=NULL; if(ptr->potato.len !=0) { prv=_load_enc_privkey_chunk(ptr->keyblob, ptr->potato); } else { if(debug) print_abac_key("abac_key_private_key",ptr); prv=_load_privkey_chunk(ptr->keyblob); /* try to use callback to retrieve the potato token */ if(prv == NULL && ptr->filename) { chunk_t pp=abac_get_potato_cb(2, ptr->filename); if(pp.len != 0) { prv=_load_enc_privkey_chunk(ptr->keyblob, pp); ptr->potato=pp; } } } return prv; } chunk_t abac_key_load_privkey_file(char *filename) { chunk_t blob=chunk_empty; struct stat sb; void *addr; int fd; if(!file_exist(filename)) return chunk_empty; fd = open(filename, O_RDONLY); if (fd == -1) { printf("warning, can not open the %s\n",filename); return blob; } if (fstat(fd, &sb) == -1) { printf("warning, key file(%s) is empty\n",filename); close(fd); return blob; } addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) { printf("warning, mapping '%s' failed\n", filename); close(fd); return blob; } blob.ptr=strndup(addr, sb.st_size); blob.len=sb.st_size; munmap(addr, sb.st_size); close(fd); return blob; } /** * Generate a private key. */ static chunk_t _generate_keyblob(void) { private_key_t *key=NULL; chunk_t encoding=chunk_empty; libabac_init(); // generate the key key = lib->creds->create( lib->creds, CRED_PRIVATE_KEY, KEY_RSA, BUILD_KEY_SIZE, 2048, BUILD_END ); if (key == NULL) errx(1, "Key generation failed"); int ret = key->get_encoding(key, PRIVKEY_PEM, &encoding); if (!ret) { DESTROY_IF(key); errx(1, "Couldn't encode private key"); } /* HACK.. it seems encoding ptr's string is often longer than encoding len */ char *new_ptr=strndup(encoding.ptr,encoding.len); free(encoding.ptr); encoding.ptr=new_ptr; DESTROY_IF(key); return encoding; } /** * Write the private key to a file. * Returns false if there's no private key loaded */ int abac_key_write_privkey(abac_key_t *key, FILE *out) { fwrite(key->keyblob.ptr, key->keyblob.len, 1, out); return 1; } /** * Get a PEM-encoded chunk representing the private key */ chunk_t abac_key_chunk(abac_key_t *ptr) { return ptr->keyblob; } /*****************************************************************/ /* load with a filename */ /* load with a filename and potato */ /* load with a chunk blob */ /* load with a chunk blob and a potato */ /*****************************************************************/ abac_key_t *abac_key_file_new(char *filename, chunk_t potato) { abac_key_t *ptr = abac_xmalloc(sizeof(abac_key_t)); if(potato.len != 0) ptr->potato=potato; else ptr->potato=chunk_empty; ptr->keyblob=abac_key_load_privkey_file(filename); ptr->filename=abac_xstrdup(filename); return ptr; } /* just use the keyblob, did not reallocate */ abac_key_t *abac_key_chunk_new(chunk_t keyblob, chunk_t potato) { abac_key_t *ptr = abac_xmalloc(sizeof(abac_key_t)); if(potato.len != 0) ptr->potato=potato; else ptr->potato=chunk_empty; ptr->keyblob=keyblob; ptr->filename=NULL; return ptr; } abac_key_t *abac_key_generate() { abac_key_t *ptr = abac_xmalloc(sizeof(abac_key_t)); ptr->potato=chunk_empty; ptr->filename=NULL; ptr->keyblob=_generate_keyblob(); return ptr; } void abac_key_free(abac_key_t *ptr) { if(ptr->potato.len != 0) chunk_clear(&ptr->potato); if(debug) { printf("FREEEEE abac_key loc(%d)\n",(int)ptr->keyblob.ptr); } chunk_clear(&ptr->keyblob); free(ptr); }