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