refactored credential builder
[strongswan.git] / src / libstrongswan / plugins / pubkey / pubkey_public_key.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Copyright (C) 2000-2008 Andreas Steffen
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 * $Id$
18 */
19
20 #include "pubkey_public_key.h"
21
22 #include <debug.h>
23 #include <asn1/pem.h>
24 #include <asn1/oid.h>
25 #include <asn1/asn1.h>
26 #include <asn1/asn1_parser.h>
27
28 /**
29 * ASN.1 definition of a subjectPublicKeyInfo structure
30 */
31 static const asn1Object_t pkinfoObjects[] = {
32 { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
33 { 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
34 { 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */
35 { 0, "exit", ASN1_EOC, ASN1_EXIT }
36 };
37 #define PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM 1
38 #define PKINFO_SUBJECT_PUBLIC_KEY 2
39
40
41 /**
42 * Load a public key from an ASN1 encoded blob
43 */
44 static public_key_t *load(chunk_t blob)
45 {
46 asn1_parser_t *parser;
47 chunk_t object;
48 int objectID;
49 public_key_t *key = NULL;
50 key_type_t type = KEY_ANY;
51
52 parser = asn1_parser_create(pkinfoObjects, blob);
53
54 while (parser->iterate(parser, &objectID, &object))
55 {
56 switch (objectID)
57 {
58 case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
59 {
60 int oid = asn1_parse_algorithmIdentifier(object,
61 parser->get_level(parser)+1, NULL);
62
63 if (oid == OID_RSA_ENCRYPTION)
64 {
65 type = KEY_RSA;
66 }
67 else if (oid == OID_EC_PUBLICKEY)
68 {
69 /* we need the whole subjectPublicKeyInfo for EC public keys */
70 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
71 KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
72 goto end;
73 }
74 else
75 {
76 /* key type not supported */
77 goto end;
78 }
79 break;
80 }
81 case PKINFO_SUBJECT_PUBLIC_KEY:
82 if (object.len > 0 && *object.ptr == 0x00)
83 {
84 /* skip initial bit string octet defining 0 unused bits */
85 object = chunk_skip(object, 1);
86 }
87 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
88 BUILD_BLOB_ASN1_DER, object, BUILD_END);
89 break;
90 }
91 }
92
93 end:
94 parser->destroy(parser);
95 free(blob.ptr);
96 return key;
97 }
98
99 typedef struct private_builder_t private_builder_t;
100 /**
101 * Builder implementation for key loading
102 */
103 struct private_builder_t {
104 /** implements the builder interface */
105 builder_t public;
106 /** loaded public key */
107 public_key_t *key;
108 };
109
110 /**
111 * Implementation of builder_t.build
112 */
113 static public_key_t *build(private_builder_t *this)
114 {
115 public_key_t *key = this->key;
116
117 free(this);
118 return key;
119 }
120
121 /**
122 * Implementation of builder_t.add
123 */
124 static void add(private_builder_t *this, builder_part_t part, ...)
125 {
126 if (!this->key)
127 {
128 va_list args;
129 chunk_t blob;
130
131 switch (part)
132 {
133 case BUILD_BLOB_ASN1_DER:
134 {
135 va_start(args, part);
136 blob = va_arg(args, chunk_t);
137 this->key = load(chunk_clone(blob));
138 va_end(args);
139 return;
140 }
141 case BUILD_BLOB_ASN1_PEM:
142 {
143 bool pgp;
144 char *pem;
145
146 va_start(args, part);
147 pem = va_arg(args, char *);
148 blob = chunk_clone(chunk_create(pem, strlen(pem)));
149 if (pem_to_bin(&blob, &chunk_empty, &pgp))
150 {
151 this->key = load(chunk_clone(blob));
152 }
153 free(blob.ptr);
154 va_end(args);
155 return;
156 }
157 default:
158 break;
159 }
160 }
161 DESTROY_IF(this->key);
162 builder_cancel(&this->public);
163 }
164
165 /**
166 * Builder construction function
167 */
168 builder_t *pubkey_public_key_builder(key_type_t type)
169 {
170 private_builder_t *this;
171
172 if (type != KEY_ANY)
173 {
174 return NULL;
175 }
176
177 this = malloc_thing(private_builder_t);
178
179 this->key = NULL;
180 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
181 this->public.build = (void*(*)(builder_t *this))build;
182
183 return &this->public;
184 }
185