source: libabac/abac_id.c @ 9e063cb

abac0-leakabac0-meimei-idmei-rt0-nmei_rt0tvf-new-xml
Last change on this file since 9e063cb was 9e063cb, checked in by Mei <mei@…>, 11 years ago

1) test out using encrypted private key to generate id credential

  • Property mode set to 100644
File size: 8.1 KB
Line 
1
2/* abac_id.c */
3
4// include the GNU extension of asprintf
5#define _GNU_SOURCE
6#include <stdio.h>
7#include <string.h>
8
9#include <assert.h>
10#include <err.h>
11#include <time.h>
12
13#include "libabac_common.h"
14#include "abac_util.h"
15#include "abac_openssl.h"
16
17#define KEY_SUFFIX  "_private.pem"
18#define CERT_SUFFIX "_ID.pem"
19
20// ID object
21//
22struct _abac_id_t {
23    char *keyid;
24    char *cn;
25    X509 *cert;
26    EVP_PKEY *key;
27
28    int refcount;
29};
30
31/**************************************************************/
32/**
33 * Helper function for building a ID from a cert. Used by
34 * abac_id_from_*
35 */
36abac_id_t *_id_from_cert(X509 *cert) {
37    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
38    id->keyid = NULL;
39    id->cn = NULL;
40    id->cert = cert;
41    id->key = NULL;
42
43    id->keyid = abac_get_keyid(id->cert);
44    id->cn = abac_get_cn(cert);
45
46    id->refcount = 1;
47
48    return id;
49}
50
51/**
52 * Load an ID cert from a file.
53 */
54abac_id_t *abac_id_from_file(char *filename) {
55
56    FILE *fp=fopen(filename,"r");
57    if(fp==NULL)
58        return NULL;
59
60    X509 *cert = abac_load_id_from_fp(fp);
61    fclose(fp);
62
63    if (cert == NULL)
64        return NULL;
65
66    return _id_from_cert(cert);
67}
68
69/**
70 * Load an ID cert from a chunk.
71 */
72abac_id_t *abac_id_from_chunk(abac_chunk_t chunk) {
73
74    X509 *cert= abac_load_id_from_chunk(chunk.ptr, chunk.len);
75
76    if (cert == NULL)
77        return NULL;
78
79    return _id_from_cert(cert);
80}
81
82static EVP_PKEY *_load_privkey_from_file(char *filename)
83{
84    FILE *fp=fopen(filename,"r");
85    if(fp==NULL) return NULL;
86    EVP_PKEY *key=abac_load_privkey_from_fp(fp);
87    fclose(fp);
88    return key;
89}
90
91/**
92 * Load private key for a cert.
93 */
94int abac_id_privkey_from_file(abac_id_t *id, char *filename) {
95    assert(id != NULL);
96
97    EVP_PKEY *key=_load_privkey_from_file(filename);
98    if (key == NULL) return ABAC_FAILURE;
99
100/* needs to make sure that the key matches up with the id */
101    /* extract the pub key from the id */
102    EVP_PKEY *pubkey=extract_pubkey_from_cert(id->cert);
103    /* cmp will just compare the pub key part of the key to see
104       if they are the same */
105    if(!EVP_PKEY_cmp(pubkey, key)) {
106        fprintf(stderr,"wrong private key for the cert!!\n");
107        return ABAC_FAILURE;
108    }
109
110    id->key = key;
111    return ABAC_SUCCESS;
112}
113
114/**
115 * Generate an ID with the specified CN and validity.
116 *
117 * validity is measured in seconds (as of 0.2.0)
118 */
119int abac_id_generate(abac_id_t **ret, char *cn, long validity) {
120    if (cn == NULL || !abac_clean_name(cn))
121        return ABAC_GENERATE_INVALID_CN;
122
123    if (validity < 0)
124        return ABAC_GENERATE_INVALID_VALIDITY;
125
126    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
127
128    id->cn = abac_xstrdup(cn);
129    id->key = abac_generate_key();
130    id->cert = abac_generate_cert(id->key, cn, validity);
131    id->keyid = abac_get_keyid(id->cert);
132
133    id->refcount = 1;
134
135    *ret = id;
136    return ABAC_SUCCESS;
137}
138
139/**
140 * Generate an ID with the specified CN and validity.
141 *
142 * validity is measured in seconds (as of 0.2.0)
143 */
144int abac_id_generate_with_key(abac_id_t **ret, char *cn, long validity, char *keyfile) {
145    if (cn == NULL || !abac_clean_name(cn))
146        return ABAC_GENERATE_INVALID_CN;
147
148    if (validity < 0)
149        return ABAC_GENERATE_INVALID_VALIDITY;
150
151    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
152
153    id->cn = abac_xstrdup(cn);
154    id->key = _load_privkey_from_file(keyfile);
155    id->cert = abac_generate_cert(id->key, cn, validity);
156    id->keyid = abac_get_keyid(id->cert);
157    id->refcount = 1;
158
159    *ret = id;
160    return ABAC_SUCCESS;
161}
162
163char *abac_id_keyid(abac_id_t *id) {
164    if(id) return id->keyid;
165        return NULL;
166}
167
168/**
169 * Get the issuer of an ID cert.
170 * Returns a malloc'd string that must be free'd.
171 */
172char *abac_id_issuer(abac_id_t *id) {
173    if(id) return abac_get_issuer(id->cert);
174        else return NULL;
175}
176
177/**
178 * Gets the subject DN of an ID cert.
179 * Returns a malloc'd string that must be free'd.
180 */
181char *abac_id_subject(abac_id_t *id) {
182    if(id) return abac_get_subject(id->cert);
183        else return NULL;
184}
185
186/**
187 * Get the validity period.
188 */
189int abac_id_validity(abac_id_t *id,struct tm *not_before,struct tm *not_after) {
190    assert(id);
191    if(abac_check_validity(id->cert, not_before, not_after)==0)
192        return ABAC_SUCCESS;
193    return ABAC_FAILURE;
194}
195
196X509 *abac_id_cert(abac_id_t *id) {
197    assert(id);
198    return id->cert;
199}
200
201// get the private key from the ID
202// will return NULL if no key has been loaded
203EVP_PKEY *abac_id_privkey(abac_id_t *id) {
204    assert(id);
205    return id->key;
206}
207
208int abac_id_has_privkey(abac_id_t *id) {
209    if(id && (id->key !=NULL))
210        return 1;
211    return 0;
212}
213
214// see if keyid is the same as id's
215int abac_id_has_keyid(abac_id_t *id, char *keyid)
216{
217    assert(id); assert(keyid);
218    if(strcmp(id->keyid, keyid) == 0)
219        return 1;
220    return 0;
221}
222
223/*
224   return a chunk with both id and key info,
225   err if missing privkey
226*/
227int abac_id_PEM(abac_id_t *id, abac_chunk_t *chunk) {
228    if(id==NULL)
229        return ABAC_CERT_MISSING_ISSUER;
230    if(id->key == NULL)
231        return ABAC_CERT_SIGNER_NOKEY;
232
233    unsigned char *kptr=NULL;
234    unsigned char *ptr=abac_string_cert(id->cert);
235    if(id->key)
236        kptr=abac_string_privkey(id->key);
237    int len=0;
238   
239    char *tmp=NULL;
240    if(kptr)  {
241        asprintf(&tmp,"%s%s", ptr,kptr);
242        free(ptr);
243        free(kptr);
244        } else {
245            tmp=(char *)ptr;
246    }
247    len=strlen(tmp);
248
249    chunk->ptr=(unsigned char *)tmp;
250    chunk->len=len;
251    return ABAC_CERT_SUCCESS;
252}
253
254abac_chunk_t abac_id_in_PEM(abac_id_t *id) {
255    assert(id);
256    unsigned char *ptr=abac_string_cert(id->cert);
257    int len=0;
258    if(ptr)
259        len=strlen((char *)ptr);
260    abac_chunk_t ret = {ptr, len };
261    return ret;
262}
263
264
265int abac_id_still_valid(abac_id_t *id) {
266    assert(id);
267    return abac_still_valid(id->cert);
268}
269
270/**
271 * Get the default filename for the cert. Value must be freed by caller.
272 */
273char *abac_id_cert_filename(abac_id_t *id) {
274    assert(id != NULL);
275    assert(id->cn != NULL);
276
277    // malloc the filename
278    int len = strlen(id->cn) + strlen(CERT_SUFFIX) + 1;
279    char *filename = abac_xmalloc(len);
280    sprintf(filename, "%s" CERT_SUFFIX, id->cn);
281
282    return filename;
283}
284
285/**
286 * Write the ID cert to an open file pointer.
287 * pem format
288 */
289int abac_id_write_cert(abac_id_t *id, FILE *out) {
290    assert(id != NULL);
291
292    int ret=abac_write_id_to_fp(id->cert, out);
293    if(ret) return ABAC_FAILURE; 
294    return ABAC_SUCCESS;
295}
296
297/**
298 * Default private key filename. Value must be freed by caller.
299 */
300char *abac_id_privkey_filename(abac_id_t *id) {
301    assert(id != NULL);
302    assert(id->cn != NULL);
303
304    // malloc the filename
305    int len = strlen(id->cn) + strlen(KEY_SUFFIX) + 1;
306    char *filename = abac_xmalloc(len);
307    sprintf(filename, "%s" KEY_SUFFIX, id->cn);
308
309    return filename;
310}
311
312/**
313 * Write the private key to a file.
314 * Returns false if there's no private key loaded
315 * PEM format
316 */
317int abac_id_write_privkey(abac_id_t *id, FILE *out) {
318    assert(id != NULL);
319    if (id->key == NULL)
320        return ABAC_FAILURE;
321
322    int ret=abac_write_privkey_to_fp(id->key, out);
323    if (ret)
324        return ABAC_FAILURE;
325
326    return ABAC_SUCCESS;
327}
328
329/**
330 * Get a abac_chunk representing the id cert.
331 */
332abac_chunk_t abac_id_cert_chunk(abac_id_t *id) {
333
334    assert(id); assert(id->cert);
335    unsigned char *ptr=abac_string_cert(id->cert);
336    int len=0;
337    if(ptr) len=strlen( (char *)ptr);
338
339    abac_chunk_t ret = { ptr, len };
340    return ret;
341}
342
343/**
344 * Get a abac_chunk representing the privkey cert.
345 */
346abac_chunk_t abac_id_privkey_chunk(abac_id_t *id) {
347
348    assert(id); assert(id->key);
349    unsigned char *ptr=abac_string_privkey(id->key);
350    int len=0;
351    if(ptr) len=strlen( (char *)ptr);
352
353    abac_chunk_t ret = { ptr, len };
354    return ret;
355}
356
357
358/**
359 * Copy a ID. Actually just increases its reference count.
360 */
361abac_id_t *abac_id_dup(abac_id_t *id) {
362    assert(id);
363    ++id->refcount;
364    return id;
365}
366
367void abac_id_free(abac_id_t *id) {
368    if (id == NULL)
369        return;
370
371    --id->refcount;
372    if (id->refcount > 0)
373        return;
374
375    // free once the reference count reaches 0
376    X509_free(id->cert);
377    EVP_PKEY_free(id->key);
378
379    free(id->keyid);
380    free(id);
381}
382
Note: See TracBrowser for help on using the repository browser.