ECB mode added to the DES plugin
[strongswan.git] / src / libstrongswan / plugins / padlock / padlock_plugin.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "padlock_plugin.h"
19 #include "padlock_aes_crypter.h"
20 #include "padlock_sha1_hasher.h"
21 #include "padlock_rng.h"
22
23 #include <stdio.h>
24
25 #include <library.h>
26 #include <debug.h>
27
28 typedef struct private_padlock_plugin_t private_padlock_plugin_t;
29 typedef enum padlock_feature_t padlock_feature_t;
30
31 /**
32 * Feature flags of padlock, received via cpuid()
33 */
34 enum padlock_feature_t {
35 PADLOCK_RESERVED_1 = (1<<0),
36 PADLOCK_RESERVED_2 = (1<<1),
37 PADLOCK_RNG_AVAILABLE = (1<<2),
38 PADLOCK_RNG_ENABLED = (1<<3),
39 PADLOCK_RESERVED_3 = (1<<4),
40 PADLOCK_RESERVED_4 = (1<<5),
41 PADLOCK_ACE_AVAILABLE = (1<<6),
42 PADLOCK_ACE_ENABLED = (1<<7),
43 PADLOCK_ACE2_AVAILABLE = (1<<8),
44 PADLOCK_ACE2_ENABLED = (1<<9),
45 PADLOCK_PHE_AVAILABLE = (1<<10),
46 PADLOCK_PHE_ENABLED = (1<<11),
47 PADLOCK_PMM_AVAILABLE = (1<<12),
48 PADLOCK_PMM_ENABLED = (1<<13),
49 };
50
51 /**
52 * private data of aes_plugin
53 */
54 struct private_padlock_plugin_t {
55
56 /**
57 * public functions
58 */
59 padlock_plugin_t public;
60
61 /**
62 * features supported by Padlock
63 */
64 padlock_feature_t features;
65 };
66
67 /**
68 * Get cpuid for info, return eax, ebx, ecx and edx. -fPIC requires to save ebx.
69 */
70 #define cpuid(op, a, b, c, d)\
71 asm (\
72 "pushl %%ebx \n\t"\
73 "cpuid \n\t"\
74 "movl %%ebx, %1 \n\t"\
75 "popl %%ebx \n\t"\
76 : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
77 : "a" (op));
78
79 /**
80 * Get features supported by Padlock
81 */
82 static padlock_feature_t get_padlock_features()
83 {
84 char vendor[3 * sizeof(int) + 1];
85 int a, b, c, d;
86
87 cpuid(0, a, b, c, d);
88 /* VendorID string is in b-d-c (yes, in this order) */
89 snprintf(vendor, sizeof(vendor), "%.4s%.4s%.4s", &b, &d, &c);
90
91 /* check if we have a VIA chip */
92 if (streq(vendor, "CentaurHauls"))
93 {
94 cpuid(0xC0000000, a, b, c, d);
95 /* check Centaur Extended Feature Flags */
96 if (a >= 0xC0000001)
97 {
98 cpuid(0xC0000001, a, b, c, d);
99 return d;
100 }
101 }
102 DBG1("Padlock not found, CPU is %s\n", vendor);
103 return 0;
104 }
105
106 /**
107 * Implementation of aes_plugin_t.destroy
108 */
109 static void destroy(private_padlock_plugin_t *this)
110 {
111 if (this->features & PADLOCK_RNG_ENABLED)
112 {
113 lib->crypto->remove_rng(lib->crypto,
114 (rng_constructor_t)padlock_rng_create);
115 lib->crypto->remove_rng(lib->crypto,
116 (rng_constructor_t)padlock_rng_create);
117 lib->crypto->remove_rng(lib->crypto,
118 (rng_constructor_t)padlock_rng_create);
119 }
120 if (this->features & PADLOCK_ACE2_ENABLED)
121 {
122 lib->crypto->remove_crypter(lib->crypto,
123 (crypter_constructor_t)padlock_aes_crypter_create);
124 }
125 if (this->features & PADLOCK_PHE_ENABLED)
126 {
127 lib->crypto->remove_hasher(lib->crypto,
128 (hasher_constructor_t)padlock_sha1_hasher_create);
129 }
130 free(this);
131 }
132
133 /*
134 * see header file
135 */
136 plugin_t *plugin_create()
137 {
138 private_padlock_plugin_t *this = malloc_thing(private_padlock_plugin_t);
139
140 this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
141
142 this->features = get_padlock_features();
143 if (!this->features)
144 {
145 free(this);
146 return NULL;
147 }
148 DBG1("Padlock found, supports:%s%s%s%s%s, enabled:%s%s%s%s%s",
149 this->features & PADLOCK_RNG_AVAILABLE ? " RNG" : "",
150 this->features & PADLOCK_ACE_AVAILABLE ? " ACE" : "",
151 this->features & PADLOCK_ACE2_AVAILABLE ? " ACE2" : "",
152 this->features & PADLOCK_PHE_AVAILABLE ? " PHE" : "",
153 this->features & PADLOCK_PMM_AVAILABLE ? " PMM" : "",
154 this->features & PADLOCK_RNG_ENABLED ? " RNG" : "",
155 this->features & PADLOCK_ACE_ENABLED ? " ACE" : "",
156 this->features & PADLOCK_ACE2_ENABLED ? " ACE2" : "",
157 this->features & PADLOCK_PHE_ENABLED ? " PHE" : "",
158 this->features & PADLOCK_PMM_ENABLED ? " PMM" : "");
159
160 if (this->features & PADLOCK_RNG_ENABLED)
161 {
162 lib->crypto->add_rng(lib->crypto, RNG_REAL,
163 (rng_constructor_t)padlock_rng_create);
164 lib->crypto->add_rng(lib->crypto, RNG_STRONG,
165 (rng_constructor_t)padlock_rng_create);
166 lib->crypto->add_rng(lib->crypto, RNG_WEAK,
167 (rng_constructor_t)padlock_rng_create);
168 }
169 if (this->features & PADLOCK_ACE2_ENABLED)
170 {
171 lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC,
172 (crypter_constructor_t)padlock_aes_crypter_create);
173 }
174 if (this->features & PADLOCK_PHE_ENABLED)
175 {
176 lib->crypto->add_hasher(lib->crypto, HASH_SHA1,
177 (hasher_constructor_t)padlock_sha1_hasher_create);
178 }
179 return &this->public.plugin;
180 }