Implemented BUILD_BLOB_ASN1_DER for the CERT_TRUSTED_PUBKEY subtype
[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 ASN.1 encoded blob
43 * Also used by pubkey_cert.c
44 */
45 public_key_t *pubkey_public_key_load(chunk_t blob)
46 {
47 asn1_parser_t *parser;
48 chunk_t object;
49 int objectID;
50 public_key_t *key = NULL;
51 key_type_t type = KEY_ANY;
52
53 parser = asn1_parser_create(pkinfoObjects, blob);
54
55 while (parser->iterate(parser, &objectID, &object))
56 {
57 switch (objectID)
58 {
59 case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
60 {
61 int oid = asn1_parse_algorithmIdentifier(object,
62 parser->get_level(parser)+1, NULL);
63
64 if (oid == OID_RSA_ENCRYPTION)
65 {
66 type = KEY_RSA;
67 }
68 else if (oid == OID_EC_PUBLICKEY)
69 {
70 /* we need the whole subjectPublicKeyInfo for EC public keys */
71 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
72 KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
73 goto end;
74 }
75 else
76 {
77 /* key type not supported */
78 goto end;
79 }
80 break;
81 }
82 case PKINFO_SUBJECT_PUBLIC_KEY:
83 if (object.len > 0 && *object.ptr == 0x00)
84 {
85 /* skip initial bit string octet defining 0 unused bits */
86 object = chunk_skip(object, 1);
87 }
88 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
89 BUILD_BLOB_ASN1_DER, object, BUILD_END);
90 break;
91 }
92 }
93
94 end:
95 parser->destroy(parser);
96 free(blob.ptr);
97 return key;
98 }
99
100 typedef struct private_builder_t private_builder_t;
101 /**
102 * Builder implementation for key loading
103 */
104 struct private_builder_t {
105 /** implements the builder interface */
106 builder_t public;
107 /** loaded public key */
108 public_key_t *key;
109 };
110
111 /**
112 * Implementation of builder_t.build
113 */
114 static public_key_t *build(private_builder_t *this)
115 {
116 public_key_t *key = this->key;
117
118 free(this);
119 return key;
120 }
121
122 /**
123 * Implementation of builder_t.add
124 */
125 static void add(private_builder_t *this, builder_part_t part, ...)
126 {
127 if (!this->key)
128 {
129 va_list args;
130 chunk_t blob;
131
132 switch (part)
133 {
134 case BUILD_BLOB_ASN1_DER:
135 {
136 va_start(args, part);
137 blob = va_arg(args, chunk_t);
138 this->key = pubkey_public_key_load(chunk_clone(blob));
139 va_end(args);
140 return;
141 }
142 case BUILD_BLOB_ASN1_PEM:
143 {
144 bool pgp;
145 char *pem;
146
147 va_start(args, part);
148 pem = va_arg(args, char *);
149 blob = chunk_clone(chunk_create(pem, strlen(pem)));
150 if (pem_to_bin(&blob, &chunk_empty, &pgp))
151 {
152 this->key = pubkey_public_key_load(chunk_clone(blob));
153 }
154 free(blob.ptr);
155 va_end(args);
156 return;
157 }
158 default:
159 break;
160 }
161 }
162 DESTROY_IF(this->key);
163 builder_cancel(&this->public);
164 }
165
166 /**
167 * Builder construction function
168 */
169 builder_t *pubkey_public_key_builder(key_type_t type)
170 {
171 private_builder_t *this;
172
173 if (type != KEY_ANY)
174 {
175 return NULL;
176 }
177
178 this = malloc_thing(private_builder_t);
179
180 this->key = NULL;
181 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
182 this->public.build = (void*(*)(builder_t *this))build;
183
184 return &this->public;
185 }
186