4105f58be2533998e4c7bba831603330b3b9c066
[strongswan.git] / src / libstrongswan / plugins / gmp / gmp_public_key.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2000-2008 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include "gmp_public_key.h"
20
21 #include <debug.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 ASN1 encoded blob
41 */
42 static public_key_t *load(chunk_t blob)
43 {
44 asn1_parser_t *parser;
45 chunk_t object;
46 int objectID;
47 public_key_t *key = NULL;
48 key_type_t type = KEY_ANY;
49
50 parser = asn1_parser_create(pkinfoObjects, blob);
51
52 while (parser->iterate(parser, &objectID, &object))
53 {
54 switch (objectID)
55 {
56 case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
57 {
58 int oid = asn1_parse_algorithmIdentifier(object,
59 parser->get_level(parser)+1, NULL);
60
61 if (oid == OID_RSA_ENCRYPTION)
62 {
63 type = KEY_RSA;
64 }
65 else
66 {
67 /* key type not supported */
68 goto end;
69 }
70 break;
71 }
72 case PKINFO_SUBJECT_PUBLIC_KEY:
73 if (object.len > 0 && *object.ptr == 0x00)
74 {
75 /* skip initial bit string octet defining 0 unused bits */
76 object = chunk_skip(object, 1);
77 }
78 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
79 BUILD_BLOB_ASN1_DER, chunk_clone(object),
80 BUILD_END);
81 break;
82 }
83 }
84
85 end:
86 parser->destroy(parser);
87 free(blob.ptr);
88 return key;
89 }
90
91 typedef struct private_builder_t private_builder_t;
92 /**
93 * Builder implementation for key loading
94 */
95 struct private_builder_t {
96 /** implements the builder interface */
97 builder_t public;
98 /** loaded public key */
99 public_key_t *key;
100 };
101
102 /**
103 * Implementation of builder_t.build
104 */
105 static public_key_t *build(private_builder_t *this)
106 {
107 public_key_t *key = this->key;
108
109 free(this);
110 return key;
111 }
112
113 /**
114 * Implementation of builder_t.add
115 */
116 static void add(private_builder_t *this, builder_part_t part, ...)
117 {
118 va_list args;
119
120 if (this->key)
121 {
122 DBG1("ignoring surplus build part %N", builder_part_names, part);
123 return;
124 }
125 switch (part)
126 {
127 case BUILD_BLOB_ASN1_DER:
128 {
129 va_start(args, part);
130 this->key = load(va_arg(args, chunk_t));
131 va_end(args);
132 break;
133 }
134 default:
135 DBG1("ignoring unsupported build part %N", builder_part_names, part);
136 break;
137 }
138 }
139
140 /**
141 * Builder construction function
142 */
143 builder_t *gmp_public_key_builder(key_type_t type)
144 {
145 private_builder_t *this;
146
147 if (type != KEY_ANY)
148 {
149 return NULL;
150 }
151
152 this = malloc_thing(private_builder_t);
153
154 this->key = NULL;
155 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
156 this->public.build = (void*(*)(builder_t *this))build;
157
158 return &this->public;
159 }
160