ECDSA with OpenSSL
[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/oid.h>
24 #include <asn1/asn1.h>
25 #include <asn1/asn1_parser.h>
26
27 /**
28 * ASN.1 definition of a subjectPublicKeyInfo structure
29 */
30 static const asn1Object_t pkinfoObjects[] = {
31 { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
32 { 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
33 { 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */
34 { 0, "exit", ASN1_EOC, ASN1_EXIT }
35 };
36 #define PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM 1
37 #define PKINFO_SUBJECT_PUBLIC_KEY 2
38
39
40 /**
41 * Load a public key from an ASN1 encoded blob
42 */
43 static public_key_t *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,
70 CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
71 chunk_clone(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, chunk_clone(object),
89 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 va_list args;
128
129 if (this->key)
130 {
131 DBG1("ignoring surplus build part %N", builder_part_names, part);
132 return;
133 }
134 switch (part)
135 {
136 case BUILD_BLOB_ASN1_DER:
137 {
138 va_start(args, part);
139 this->key = load(va_arg(args, chunk_t));
140 va_end(args);
141 break;
142 }
143 default:
144 DBG1("ignoring unsupported build part %N", builder_part_names, part);
145 break;
146 }
147 }
148
149 /**
150 * Builder construction function
151 */
152 builder_t *pubkey_public_key_builder(key_type_t type)
153 {
154 private_builder_t *this;
155
156 if (type != KEY_ANY)
157 {
158 return NULL;
159 }
160
161 this = malloc_thing(private_builder_t);
162
163 this->key = NULL;
164 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
165 this->public.build = (void*(*)(builder_t *this))build;
166
167 return &this->public;
168 }
169