Index: libabac/abac_id.c
===================================================================
--- libabac/abac_id.c	(revision f89b991618ca86176d8d202d7c2b370ac8246c38)
+++ libabac/abac_id.c	(revision 461541aae6382bb58dfb3c4a1679d2d48e8f9e64)
@@ -1,531 +1,39 @@
-/**
-**  abac_id.c
-**/
-
+
+/* abac_id.c */
+
+// include the GNU extension of asprintf
 #define _GNU_SOURCE
 #include <stdio.h>
+#include <string.h>
+
+#include <assert.h>
 #include <err.h>
-#include <assert.h>
 #include <time.h>
 
+#include "libabac_common.h"
 #include "abac_util.h"
-#include "abac_key.h"
-#include "abac_verifier.h"
-#include "abac_util_cert.h"
-
-static int debug=0;
-
-/* load id into a session when id is being created instead
-   of when id is added into a context */
-static int early_load_id=1;
-
-/* idtypename[idtype] */
-static const char * const _idtypename[] =
-{
-  "badidtype", "keyid"
-};
-static int _idtypename_cnt=1;
-
-
-// abac_id object
+#include "abac_openssl.h"
+
+#define KEY_SUFFIX  "_private.pem"
+#define CERT_SUFFIX "_ID.pem"
+
+// ID object
+//
 struct _abac_id_t {
-    int idtype;    /* default to string 'keyid' for now */
-    char *keyid; /* sha */
+    char *keyid;
     char *cn;
-    certificate_t *cert;
-    abac_key_t *key;
+    X509 *cert;
+    EVP_PKEY *key;
+
     int refcount;
 };
 
-#define KEY_SUFFIX  "_private.pem"
-#define CERT_SUFFIX "_ID.pem"
-
-
-/* local */
-char *abac_id_keyid(abac_id_t*);
-abac_id_t *abac_id_copy(abac_id_t *id);
-/****************************************************************/
-//
-// Helper functions below
-//
-int abac_idtype_lookup(char *type)
-{
-    int i;
-    for (i = 1; i <= _idtypename_cnt ; i++)
-        if(strcmp(type,_idtypename[i])==0)
-            return i;
-    return 0;
-}
-
-char *abac_idtype_string(int i)
-{
-    if(i > _idtypename_cnt) {
-        printf("bad idtypename idx %d\n", i);
-        panic("abac_idtype_string: went out of range on idtypename");
-    }
-    return (char*) _idtypename[i];
-}
-
-
-static char *_create_dn(char *cn)
-{
-#define DN "cn="
-
-    char *dn = abac_xmalloc(sizeof(DN) + strlen(cn));
-    memcpy(dn, DN, sizeof(DN));
-    strcat(dn, cn);
-
-    return dn;
-}
-
-void abac_id_dump_from_id(abac_id_t *id)
-{
-    fprintf(stderr,"abac_id_dump_id: \n");
-    fprintf(stderr,"idtype: %d\n",id->idtype); 
-    fprintf(stderr,"keyid: %s\n",id->keyid);
-    fprintf(stderr,"cn: %s\n", id->cn);
-    fprintf(stderr,"refcount: %d\n",id->refcount);
-    if(id->key !=NULL) fprintf(stderr,"has private key\n");
-    if(id->cert !=NULL) fprintf(stderr,"has cert\n");
-}
-
-void abac_id_dump_from_cert(certificate_t *cert)
-{
-    char *ret;
-    fprintf(stderr,"abac_id_dump_from_cert: \n");
-    int rv = asprintf(&ret, "%Y", cert->get_issuer(cert));
-    fprintf(stderr,"issuer: %s\n",ret);
-    fprintf(stderr,"keyid: %s\n",cert_get_keyid(cert));
-}
-
-
-/**
- *
- * Preload ID into sessions' master list before being
- * loaded into some context
- *
-**/
-
-static int _add_into_id_credentials(abac_id_t *id)
-{
-    char *keyid=abac_id_keyid(id);
-    abac_id_credential_t *idcred=abac_id_credential_lookup(keyid);
-    if(idcred !=NULL) {
-       if(debug) fprintf(stderr,"_add_into_id_credentials: something in there for %s\n",keyid);
-       idcred=abac_id_credential_dup(idcred);
-       } else {
-          if(debug) fprintf(stderr,"_add_into_id_credentials: adding %s\n",keyid);
-          if(early_load_id) {
-             /* this id needed to be deep copyed, because it is going into our
-                session id credential list */
-             abac_id_t *nid = abac_id_copy(id);
-             idcred=abac_id_credential_new(nid);
-             abac_add_id_cred(idcred);
-          }
-    }
-}
-
-/**
- * Generate ID certificate.
- *
- * validity is measured in seconds (as of 0.2.0)
- */
-static certificate_t *_generate_cert(abac_key_t *keyptr, char *cn, int validity) {
-    // build the DN
-    char *dn_string = _create_dn(cn);
-    libabac_init();
-
-    DEBUG_PRINTF("\n_generate_cert: id cert for cn(%s)with dn(%s)\n", cn, dn_string);
-
-    identification_t *iden = identification_create_from_string(dn_string);
-    if (iden == NULL)
-        errx(1, "couldn't create ID from DN %s", dn_string);
-    free(dn_string);
-
-    // get the private key
-    private_key_t *private = abac_key_private_key(keyptr);
-    if(private == NULL)
-        errx(1, "couldn't create ID without private key");
-
-    public_key_t *public = private->get_public_key(private);
-    if (public == NULL)
-        errx(1, "couldn't get public key from private key");
-
-    // create a serial (stolen from strongswan pki)
-    rng_t *rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
-    if (!rng)
-        errx(1, "no random number generator");
-
-    // random serial
-    chunk_t serial = abac_generate_serial();
-
-    // validity period
-    time_t not_before = time(NULL);
-    time_t not_after = not_before + validity;
-
-    // create!
-    certificate_t *cert = lib->creds->create(lib->creds,
-        CRED_CERTIFICATE, CERT_X509,
-        BUILD_SIGNING_KEY, private,
-        BUILD_PUBLIC_KEY, public,
-        BUILD_SUBJECT, iden,
-        BUILD_NOT_BEFORE_TIME, not_before,
-        BUILD_NOT_AFTER_TIME, not_after,
-        BUILD_SERIAL, serial,
-        BUILD_DIGEST_ALG, HASH_SHA1,
-        BUILD_X509_FLAG, X509_CA,
-        BUILD_PATHLEN, X509_NO_CONSTRAINT,
-        BUILD_END
-    );
-    if (cert == NULL)
-        errx(1, "couldn't build cert :(");
-
-    DESTROY_IF(iden);
-    DESTROY_IF(public);
-    DESTROY_IF(private);
-    free(serial.ptr);
-
-    return cert;
-}
-
-/* from libstrongswan, chunk.h
-chunk_t chunk_from_base64(chunk_t base64, char *buf);
-chunk_t chunk_to_base64(chunk_t chunk, char *buf);
-    chunk_t b64 = chunk_to_base64(chunk, NULL);
-    chunk_t chk = chunk_from_base64(base64, NULL); 
-*/
-#define BYTES_PER_LINE 64
-
-// thx libstrongswan
-static void _encode_base64(FILE *out, chunk_t encoding) {
-    int start;
-
-    chunk_t b64 = chunk_to_base64(encoding, NULL);
-
-    fprintf(out, "-----BEGIN CERTIFICATE-----\n");
-
-    for (start = 0; start < b64.len; start += BYTES_PER_LINE) {
-        int left = b64.len - start;
-        int len = left < BYTES_PER_LINE ? left : BYTES_PER_LINE;
-        fwrite(b64.ptr + start, len, 1, out);
-        fprintf(out, "\n");
-    }
-
-    fprintf(out, "-----END CERTIFICATE-----\n");
-
-    free(b64.ptr);
-}
-/****************************************************************/
-int abac_id_idtype(abac_id_t *id)
-{
-    assert(id != NULL);
-    return id->idtype;
-}
-
-char* abac_id_idtype_string(abac_id_t *id)
-{
-    assert(id != NULL);
-    return abac_idtype_string(id->idtype);
-}
-
-char *abac_id_keyid(abac_id_t *id) {
-    assert(id != NULL);
-    return id->keyid;
-}
-
-char *abac_id_cn(abac_id_t *id) {
-    assert(id != NULL);
-    return id->cn;
-}
-
-static int _abac_id_set_cn(abac_id_t *id, char* cn) {
-    if(cn) {
-        if(id->cn != NULL)
-            free(id->cn);
-        id->cn = abac_xstrdup(cn);
-    }
-    return 0;
-}
-
-
-char *abac_id_name(abac_id_t *id)
-{
-    assert(id != NULL);
-    if(USE("ABAC_CN"))
-        return abac_id_cn(id);
-    else return abac_id_keyid(id);
-}
-
-char *abac_id_string(abac_id_t *id) 
-{
-    char *tmp=NULL;
-    if(abac_id_has_privkey(id)) 
-        asprintf(&tmp,"(%s,%s,y)",abac_id_name(id),abac_id_idtype_string(id));
-        else asprintf(&tmp,"(%s,%s,n)",abac_id_name(id),abac_id_idtype_string(id));
-    return tmp;
-}
-
-/**
- * Get the issuer of an ID cert.
- * Returns a malloc'd string that must be free'd.
- */
-char *abac_id_issuer(abac_id_t *id) {
-    char *ret;
-    int rv = asprintf(&ret, "%Y", id->cert->get_issuer(id->cert));
-
-    if (rv < 0)
-        err(1, "couldn't malloc string for issuer\n");
-
-    return ret;
-}
-
-int abac_id_lastone(abac_id_t *ptr)
-{
-    assert(ptr);
-    if(ptr->refcount == 1)
-        return 1;
-    return 0;
-}
-
-
-/**
- * Gets the subject DN of an ID cert.
- * Returns a malloc'd string that must be free'd.
- */
-char *abac_id_subject(abac_id_t *id) {
-    char *ret;
-    int rv = asprintf(&ret, "%Y", id->cert->get_subject(id->cert));
-
-    if (rv < 0)
-        err(1, "couldn't malloc string for subject\n");
-
-    return ret;
-}
-
-/**
- * Get the validity period.
- */
-void abac_id_validity(abac_id_t *id, time_t *not_before, time_t *not_after) {
-    id->cert->get_validity(id->cert, NULL, not_before, not_after);
-}
-
-certificate_t *abac_id_cert(abac_id_t *id)
-{
-    assert(id != NULL);
-    return id->cert;
-}
-
-private_key_t *abac_id_privkey(abac_id_t *id)
-{
-    assert(id != NULL);
-    if(id->key !=0)
-        return abac_key_private_key(id->key);
-    return NULL;
-}
-
-abac_key_t *abac_id_keyptr(abac_id_t *id)
-{
-    assert(id!=NULL);
-    return id->key;
-}
-
-int abac_id_has_privkey(abac_id_t *id)
-{
-    if(id && id->key !=0)
-       return 1;
-    return 0;
-}
-
-// convert a chunk to a lowercase binary string
-// malloc's the string
-static char *_chunk_to_string(chunk_t chunk) {
-    int i;
-
-    char *ret = abac_xmalloc(chunk.len * 2 + 1);
-
-    for (i = 0; i < chunk.len; ++i)
-        sprintf(ret + 2 * i, "%02x", chunk.ptr[i]);
-
-    return ret;
-}
-
-/**
- * Write the ID cert to an open file pointer.
- */
-void abac_id_write_cert(abac_id_t *id, FILE *out) {
-    assert(id != NULL);
-
-    chunk_t encoding = chunk_empty;
-    int rc=id->cert->get_encoding(id->cert,CERT_ASN1_DER,&encoding);
-    if(rc) {
-        _encode_base64(out, encoding);
-    }
-}
-
-/**
- * Write the private key to a file.
- * Returns false if there's no private key loaded
- */
-int abac_id_write_privkey(abac_id_t *id, FILE *out)
-{
-    return abac_key_write_privkey(id->key, out);
-}
-
-/**
- * Get a DER-encoded chunk representing the cert.
- */
-abac_chunk_t abac_id_cert_chunk(abac_id_t *id) {
-    assert(id->cert);
-    chunk_t encoding = chunk_empty;
-    int rc= id->cert->get_encoding(id->cert, CERT_ASN1_DER, &encoding);
-    abac_chunk_t ret= { encoding.ptr, encoding.len };
-    return ret;
-}
-
-/**
- * Get a PEM-encoded chunk representing the private key 
- */
-abac_chunk_t abac_id_privkey_chunk(abac_id_t *id) 
-{
-    chunk_t tmp=chunk_empty;
-    if(id->key)
-         tmp=abac_key_chunk(id->key);
-    abac_chunk_t ret= {tmp.ptr, tmp.len};
-    return ret;
-}
-
-void abac_id_print_key_chunk(abac_id_t *id)
-{
-   if(id->key)
-       print_abac_key("abac_id_print_key_chunk",id->key);
-}
-
-/**
- * Copy an abac ID. Actually just increases its reference count.
- */
-abac_id_t *abac_id_dup(abac_id_t *id)
-{
-    if(id)
-        ++id->refcount;
-    return id;
-}
-
-void abac_id_free(abac_id_t *id) {
-
-    if (id == NULL)
-        return;
-
-    DEBUG_PRINTF("\nabac_id_free: deleting id with cn(%s)with sha(%s) at(%ld)\n", id->cn, id->keyid, (long)id);
-
-    --id->refcount;
-    if (id->refcount > 0)
-        return;
-
-    // free once the reference count reaches 0
-    DESTROY_IF(id->cert);
-
-    if(id->key) {
-         DEBUG_PRINTF("abac_id_free: deleting id with cn(%s)at(%ld)key(%ld)\n", id->cn, (long)id, (long)id->key);
-         abac_key_free(id->key);
-    }
-
-    free(id->keyid);
-    free(id->cn);
-    free(id);
-}
-
-/****************************************************************/
-/**
- * Default private key filename. Value must be freed by caller.
- */
-char *abac_id_privkey_filename(abac_id_t *id) {
-    assert(id != NULL);
-    assert(id->cn != NULL);
-
-    /* this cn has pCN attached to it */
-    char *filename = NULL;
-    char* ptr=id->cn;
-    asprintf(&filename, "%s%s",(ptr+1),KEY_SUFFIX);
-    return filename;
-}
-
-/**
- * Get the default filename for the cert. Value must be freed by caller.
- */
-char *abac_id_cert_filename(abac_id_t *id) {
-    assert(id != NULL);
-    assert(id->cn != NULL);
-
-    /* this cn has pCN attached to it */
-    char *filename = NULL;
-    char* ptr=id->cn;
-    asprintf(&filename, "%s%s",(ptr+1),CERT_SUFFIX);
-    return filename;
-}
-
-/****************************************************************/
-
-/*
-** Create an ID from tidbits info
-*/
-abac_id_t *abac_id_new(int idtype,char *keyid, char *cn, 
-certificate_t *cert)
-{
-if(debug)
-   fprintf(stderr,"abac_id_new, keyid(%s), cn(%s) keyid from cert(%s)\n",
-           keyid,cn, cert_get_keyid(cert));
-
+/**************************************************************/
+/**
+ * Helper function for building a ID from a cert. Used by
+ * abac_id_from_*
+ */
+abac_id_t *_id_from_cert(X509 *cert) {
     abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
-    id->idtype = idtype;
-    id->keyid = abac_xstrdup(keyid);
-    id->cn = abac_xstrdup(cn);
-    id->cert = cert;
-    id->key = NULL;
-    id->refcount = 1;
-    _add_into_id_credentials(id);
-    return id;
-}
-
-static certificate_t *_certificate_copy(certificate_t *cert)
-{
-    chunk_t encoding = chunk_empty;
-    int rc=cert->get_encoding(cert,CERT_ASN1_DER,&encoding);
-    certificate_t *ncert = cert_get_id_cert_from_chunk(encoding);
-    return ncert;
-}
-
-/*
-    hard duplicate of an id 
-    This is used by the libabac interface for case the where
-    abac_context_load_id(abac_id_t *id) is called. We want
-    the structure being kept in libabac to be locally held
-    so that we are not subject to destructor being called on
-    the structure by some other system or being called in
-    certain way that is not fully controlled by libabac.
-*/
-abac_id_t *abac_id_copy(abac_id_t *id)
-{
-    assert(id);
-    abac_id_t *nid = abac_xmalloc(sizeof(abac_id_t));
-    nid->idtype = id->idtype;
-    nid->keyid = abac_xstrdup(id->keyid);
-    nid->cn = abac_xstrdup(id->cn);
-    nid->cert = _certificate_copy(id->cert);
-    if(id->key)
-        nid->key = abac_key_copy(id->key); 
-        else nid->key=NULL;
-    nid->refcount = id->refcount+1;
-    return nid;
-}
-
-abac_id_t *abac_id_keyid_new(char *keyid, char *cn, certificate_t *cert)
-{
-    return abac_id_new(e_KEYID,keyid,cn,cert); 
-}
-
-static abac_id_t *_abac_id_from_cert(certificate_t *cert)
-{
-    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
-    id->idtype = e_KEYID;
     id->keyid = NULL;
     id->cn = NULL;
@@ -533,63 +41,69 @@
     id->key = NULL;
 
-    id->keyid = cert_get_keyid(id->cert);
-    // get the CN from the cert
-    id_part_t type;
-    chunk_t data;
-
-    identification_t *cert_id = id->cert->get_subject(id->cert);
-    enumerator_t *id_enum = cert_id->create_part_enumerator(cert_id);
-    while (id_enum->enumerate(id_enum, &type, &data))
-        if (type == ID_PART_RDN_CN) {
-            id->cn = abac_xmalloc(data.len + 2);
-            id->cn[0]='p';
-            memcpy(&id->cn[1], data.ptr, data.len);
-            id->cn[data.len+1] = 0;
-        }
-    id_enum->destroy(id_enum);
-
-    if(id->cn != NULL) {
-        if(debug) fprintf(stderr, "_abac_id_from_cert, found cn (%s)\n", id->cn);
-        } else { /* have to prepend a p */
-            char *tmp=NULL;
-            asprintf(&tmp,"p%s",id->keyid);
-            _abac_id_set_cn(id,tmp);
-            free(tmp);
-            if(debug) fprintf(stderr,"_abac_id_from_cert, did not find cn, set it to (%s)\n", id->cn);
+    id->keyid = abac_get_keyid(id->cert);
+    id->cn = abac_get_cn(cert);
+
+    id->refcount = 1;
+
+    return id;
+}
+
+/**
+ * Load an ID cert from a file.
+ */
+abac_id_t *abac_id_from_file(char *filename) {
+
+    FILE *fp=fopen(filename,"r");
+    if(fp==NULL)
+        return NULL;
+
+    X509 *cert = abac_load_id_from_fp(fp);
+    fclose(fp);
+
+    if (cert == NULL)
+        return NULL;
+
+    return _id_from_cert(cert);
+}
+
+/**
+ * Load an ID cert from a chunk.
+ */
+abac_id_t *abac_id_from_chunk(abac_chunk_t chunk) {
+
+    X509 *cert= abac_load_id_from_chunk(chunk.ptr, chunk.len);
+
+    if (cert == NULL)
+        return NULL;
+
+    return _id_from_cert(cert);
+}
+
+/**
+ * Load private key for a cert.
+ */
+int abac_id_privkey_from_file(abac_id_t *id, char *filename) {
+    assert(id != NULL);
+
+    FILE *fp=fopen(filename,"r");
+    if(fp==NULL) return ABAC_FAILURE;
+
+    EVP_PKEY *key=abac_load_privkey_from_fp(fp);
+    fclose(fp);
+
+    if (key == NULL) return ABAC_FAILURE;
+
+/* needs to make sure that the key matches up with the id */
+    /* extract the pub key from the id */
+    EVP_PKEY *pubkey=extract_pubkey_from_cert(id->cert);
+    /* cmp will just compare the pub key part of the key to see
+       if they are the same */
+    if(!EVP_PKEY_cmp(pubkey, key)) {
+        fprintf(stderr,"wrong private key for the cert!!\n");
+        return ABAC_FAILURE;
     }
 
-    id->refcount = 1;
-    _add_into_id_credentials(id);
-    return id;
-}
-
-/**
- * Create an ID cert from a file.
- * this one does not add id into id hash list
- */
-abac_id_t *abac_id_from_file(char *filename) {
-
-    /* make sure file exists */
-    if(!file_exist(filename)) return NULL;
-
-    libabac_init();
-    certificate_t *cert = cert_get_id_cert_from_file(filename);
-
-    if (cert == NULL) return NULL;
-
-    return _abac_id_from_cert(cert);
-}
-
-/**
- * Create an ID cert from a chunk.
- */
-abac_id_t *abac_id_from_chunk(abac_chunk_t achunk)
-{
-    chunk_t chunk = { .ptr = achunk.ptr, .len = achunk.len };
-    certificate_t *cert = cert_get_id_cert_from_chunk(chunk);
-
-    if (cert == NULL) return NULL;
-
-    return _abac_id_from_cert(cert);
+    id->key = key;
+    return ABAC_SUCCESS;
 }
 
@@ -599,121 +113,242 @@
  * validity is measured in seconds (as of 0.2.0)
  */
-int abac_id_generate(abac_id_t **ret, char *cn, int validity)
+int abac_id_generate(abac_id_t **ret, char *cn, long validity) {
+    if (cn == NULL || !abac_clean_name(cn))
+        return ABAC_GENERATE_INVALID_CN;
+
+    if (validity < 0)
+        return ABAC_GENERATE_INVALID_VALIDITY;
+
+    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
+
+    id->cn = abac_xstrdup(cn);
+    id->key = abac_generate_key();
+    id->cert = abac_generate_cert(id->key, cn, validity);
+    id->keyid = abac_get_keyid(id->cert);
+
+    id->refcount = 1;
+
+    *ret = id;
+    return ABAC_SUCCESS;
+}
+
+char *abac_id_keyid(abac_id_t *id) {
+    if(id) return id->keyid;
+        return NULL;
+}
+
+/**
+ * Get the issuer of an ID cert.
+ * Returns a malloc'd string that must be free'd.
+ */
+char *abac_id_issuer(abac_id_t *id) {
+    if(id) return abac_get_issuer(id->cert);
+        else return NULL;
+}
+
+/**
+ * Gets the subject DN of an ID cert.
+ * Returns a malloc'd string that must be free'd.
+ */
+char *abac_id_subject(abac_id_t *id) {
+    if(id) return abac_get_subject(id->cert);
+        else return NULL;
+}
+
+/**
+ * Get the validity period.
+ */
+int abac_id_validity(abac_id_t *id,struct tm *not_before,struct tm *not_after) {
+    assert(id);
+    if(abac_check_validity(id->cert, not_before, not_after)==0)
+        return ABAC_SUCCESS;
+    return ABAC_FAILURE;
+}
+
+X509 *abac_id_cert(abac_id_t *id) {
+    assert(id);
+    return id->cert;
+}
+
+// get the private key from the ID
+// will return NULL if no key has been loaded
+EVP_PKEY *abac_id_privkey(abac_id_t *id) {
+    assert(id);
+    return id->key;
+}
+
+int abac_id_has_privkey(abac_id_t *id) {
+    if(id && (id->key !=NULL))
+        return 1;
+    return 0;
+}
+
+// see if keyid is the same as id's
+int abac_id_has_keyid(abac_id_t *id, char *keyid)
 {
-    if (cn == NULL || !abac_validate_clean_name(cn))
-        return ABAC_ID_GENERATE_INVALID_CN;
-
-    DEBUG_PRINTF("abac_id_generate: generating id with cn(%s)\n",cn);
-
-    if (validity < 0)
-        return ABAC_ID_GENERATE_INVALID_VALIDITY;
-
-    if (validity == 0) validity = 1080 * 86400;
-
-    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
-
+    assert(id); assert(keyid);
+    if(strcmp(id->keyid, keyid) == 0)
+        return 1;
+    return 0;
+}
+
+/*
+   return a chunk with both id and key info,
+   err if missing privkey
+*/
+int abac_id_PEM(abac_id_t *id, abac_chunk_t *chunk) {
+    if(id==NULL)
+        return ABAC_CERT_MISSING_ISSUER;
+    if(id->key == NULL)
+        return ABAC_CERT_SIGNER_NOKEY;
+
+    unsigned char *kptr=NULL;
+    unsigned char *ptr=abac_string_cert(id->cert);
+    if(id->key)
+        kptr=abac_string_privkey(id->key);
+    int len=0;
+    
     char *tmp=NULL;
-    asprintf(&tmp,"p%s",cn);
-    id->idtype = e_KEYID;
-    id->cn = tmp;
-    id->key = abac_key_generate();
-    id->cert = _generate_cert(id->key, cn, validity);
-    id->keyid = cert_get_keyid(id->cert);
-
-    id->refcount = 1;
-    _add_into_id_credentials(id);
-
-    *ret = id;
-    return ABAC_ID_SUCCESS;
-}
-
-
-/**
- * Generate an ID with the specified CN and validity and a passphrase.
- *
- * validity is measured in seconds (as of 0.2.0)
- */
-int abac_id_generate_with_key(abac_id_t **ret, char *cn, int validity, char *filename, char *pfile) {
-    if (cn == NULL || !abac_validate_clean_name(cn))
-        return ABAC_ID_GENERATE_INVALID_CN;
-
-    if(debug) {
-        fprintf(stderr,"abac_id_generate: generating id with cn(%s) and privkey(%s)",
-                                                    cn, filename);
-        if(pfile) fprintf(stderr,"pfile(%s)\n",pfile);
-            else fprintf(stderr,"\n");
+    if(kptr)  {
+        asprintf(&tmp,"%s%s", ptr,kptr);
+        free(ptr);
+        free(kptr);
+        } else {
+            tmp=ptr;
     }
-
-    if (validity < 0)
-        return ABAC_ID_GENERATE_INVALID_VALIDITY;
-
-    if (validity == 0) validity = 1080 * 86400;
-
-    chunk_t pp=chunk_empty;
-    if(pfile && strlen(pfile)!=0) {
-        if(!file_exist(pfile))
-            errx(1, "passphrase file does not exist!!\n");
-        pp=extract_potato(filename,pfile);
-    }
-
-    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
-    char *tmp=NULL;
-    asprintf(&tmp,"p%s",cn);
-    id->idtype = e_KEYID;
-    id->cn = tmp;
-    id->key = abac_key_file_new(filename,pp);
-    id->cert = _generate_cert(id->key, cn, validity);
-    id->keyid = cert_get_keyid(id->cert);
-
-    id->refcount = 1;
-    _add_into_id_credentials(id);
-    *ret = id;
-    return ABAC_ID_SUCCESS;
-}
-
-/* special handling, need to update the key of the id copy stored in
-   session's id credential list */
-static void _load_privkey_to_master_list(char *keyid, abac_key_t *key)
-{
-    abac_id_credential_t *idcred=abac_id_credential_lookup(keyid);
-    if(idcred==NULL) {
-        panic(1,"_load_privkey_to_master_list: missing id in masterlist(%s)\n", keyid);
-    }
-    abac_id_t *id=abac_id_credential_id(idcred);
-    id->key = abac_key_copy(key);
-}
-
-int abac_id_load_privkey_file(abac_id_t *ptr, char *keyfile)
-{
-    assert(ptr);
-    ptr->key=abac_key_file_new(keyfile, chunk_empty);
-    _load_privkey_to_master_list(abac_id_keyid(ptr), ptr->key);
-    return 1;
-}
-
-int abac_id_load_enc_privkey_file(abac_id_t *ptr, char *keyfile, char *pfile)
-{
-    assert(ptr);
-    chunk_t pp=extract_potato(keyfile,pfile);
-    ptr->key=abac_key_file_new(keyfile, pp);
-    _load_privkey_to_master_list(abac_id_keyid(ptr), ptr->key);
-    return 1;
-}
-
-int abac_id_load_privkey_chunk(abac_id_t *ptr, chunk_t keychunk)
-{
-    assert(ptr);
-    ptr->key=abac_key_chunk_new(keychunk, chunk_empty);
-    _load_privkey_to_master_list(abac_id_keyid(ptr), ptr->key);
-    return 1;
-}
-
-int abac_id_load_enc_privkey_chunk(abac_id_t *ptr, chunk_t keychunk, char *pfile)
-{
-    assert(ptr);
-    chunk_t pp=extract_potato(NULL,pfile);
-    ptr->key=abac_key_chunk_new(keychunk, pp);
-    _load_privkey_to_master_list(abac_id_keyid(ptr), ptr->key);
-    return 1;
-}
-
+    len=strlen(tmp);
+
+    chunk->ptr=tmp;
+    chunk->len=len;
+    return ABAC_CERT_SUCCESS;
+}
+
+abac_chunk_t abac_id_in_PEM(abac_id_t *id) {
+    assert(id);
+    unsigned char *ptr=abac_string_cert(id->cert);
+    int len=0;
+    if(ptr)
+        len=strlen((char *)ptr);
+    abac_chunk_t ret = {ptr, len };
+    return ret;
+}
+
+
+int abac_id_still_valid(abac_id_t *id) {
+    assert(id);
+    return abac_still_valid(id->cert);
+}
+
+/**
+ * Get the default filename for the cert. Value must be freed by caller.
+ */
+char *abac_id_cert_filename(abac_id_t *id) {
+    assert(id != NULL);
+    assert(id->cn != NULL);
+
+    // malloc the filename
+    int len = strlen(id->cn) + strlen(CERT_SUFFIX) + 1;
+    char *filename = abac_xmalloc(len);
+    sprintf(filename, "%s" CERT_SUFFIX, id->cn);
+
+    return filename;
+}
+
+/**
+ * Write the ID cert to an open file pointer.
+ * pem format
+ */
+int abac_id_write_cert(abac_id_t *id, FILE *out) {
+    assert(id != NULL);
+
+    int ret=abac_write_id_to_fp(id->cert, out);
+    if(ret) return ABAC_FAILURE; 
+    return ABAC_SUCCESS;
+}
+
+/**
+ * Default private key filename. Value must be freed by caller.
+ */
+char *abac_id_privkey_filename(abac_id_t *id) {
+    assert(id != NULL);
+    assert(id->cn != NULL);
+
+    // malloc the filename
+    int len = strlen(id->cn) + strlen(KEY_SUFFIX) + 1;
+    char *filename = abac_xmalloc(len);
+    sprintf(filename, "%s" KEY_SUFFIX, id->cn);
+
+    return filename;
+}
+
+/**
+ * Write the private key to a file.
+ * Returns false if there's no private key loaded
+ * PEM format
+ */
+int abac_id_write_privkey(abac_id_t *id, FILE *out) {
+    assert(id != NULL);
+    if (id->key == NULL)
+        return ABAC_FAILURE;
+
+    int ret=abac_write_privkey_to_fp(id->key, out);
+    if (ret)
+        return ABAC_FAILURE;
+
+    return ABAC_SUCCESS;
+}
+
+/**
+ * Get a abac_chunk representing the id cert.
+ */
+abac_chunk_t abac_id_cert_chunk(abac_id_t *id) {
+
+    assert(id); assert(id->cert);
+    unsigned char *ptr=abac_string_cert(id->cert);
+    int len=0;
+    if(ptr) len=strlen( (char *)ptr);
+
+    abac_chunk_t ret = { ptr, len };
+    return ret;
+}
+
+/**
+ * Get a abac_chunk representing the privkey cert.
+ */
+abac_chunk_t abac_id_privkey_chunk(abac_id_t *id) {
+
+    assert(id); assert(id->key);
+    unsigned char *ptr=abac_string_privkey(id->key);
+    int len=0;
+    if(ptr) len=strlen( (char *)ptr);
+
+    abac_chunk_t ret = { ptr, len };
+    return ret;
+}
+
+
+/**
+ * Copy a ID. Actually just increases its reference count.
+ */
+abac_id_t *abac_id_dup(abac_id_t *id) {
+    assert(id);
+    ++id->refcount;
+    return id;
+}
+
+void abac_id_free(abac_id_t *id) {
+    if (id == NULL)
+        return;
+
+    --id->refcount;
+    if (id->refcount > 0)
+        return;
+
+    // free once the reference count reaches 0
+    X509_free(id->cert);
+    EVP_PKEY_free(id->key);
+
+    free(id->keyid);
+    free(id);
+}
+
