loading PEM encoded public keys
[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,
71 CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
72 chunk_clone(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, chunk_clone(object),
90 BUILD_END);
91 break;
92 }
93 }
94
95 end:
96 parser->destroy(parser);
97 free(blob.ptr);
98 return key;
99 }
100
101 typedef struct private_builder_t private_builder_t;
102 /**
103 * Builder implementation for key loading
104 */
105 struct private_builder_t {
106 /** implements the builder interface */
107 builder_t public;
108 /** loaded public key */
109 public_key_t *key;
110 };
111
112 /**
113 * Implementation of builder_t.build
114 */
115 static public_key_t *build(private_builder_t *this)
116 {
117 public_key_t *key = this->key;
118
119 free(this);
120 return key;
121 }
122
123 /**
124 * Implementation of builder_t.add
125 */
126 static void add(private_builder_t *this, builder_part_t part, ...)
127 {
128 va_list args;
129
130 if (this->key)
131 {
132 DBG1("ignoring surplus build part %N", builder_part_names, part);
133 return;
134 }
135 va_start(args, part);
136 switch (part)
137 {
138 case BUILD_BLOB_ASN1_DER:
139 {
140 this->key = load(va_arg(args, chunk_t));
141 break;
142 }
143 case BUILD_BLOB_ASN1_PEM:
144 {
145 bool pgp;
146 char *pem;
147 chunk_t blob;
148
149 pem = va_arg(args, char *);
150 blob = chunk_clone(chunk_create(pem, strlen(pem)));
151 if (pem_to_bin(&blob, &chunk_empty, &pgp))
152 {
153 this->key = load(chunk_clone(blob));
154 }
155 free(blob.ptr);
156 break;
157 }
158 default:
159 DBG1("ignoring unsupported build part %N", builder_part_names, part);
160 break;
161 }
162 va_end(args);
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