revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / diskimage / plugins / crypt.c
blob7fd49ebaae66b3d1a13877f1ef24270cf8341a34
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
27 #define USED_PLUGIN_API_VERSION 8
28 #include <devices/diskimage.h>
29 #include <libraries/amisslmaster.h>
30 #include <libraries/amissl.h>
31 #include <proto/exec.h>
32 #include <proto/dos.h>
33 #include <proto/amisslmaster.h>
34 #include <proto/amissl.h>
35 #include <string.h>
36 #include "device_locale.h"
37 #include "rev/diskimage.device_rev.h"
39 PLUGIN_VERSTAG("Crypt")
41 extern struct DiskImagePlugin crypt_plugin;
43 PLUGIN_TABLE(&crypt_plugin)
45 struct CryptImage {
46 BPTR file;
47 APTR unit;
48 QUAD total_bytes;
49 ULONG block_size;
50 ULONG total_blocks;
51 UBYTE *buffer;
52 BOOL key_valid;
53 IDEA_KEY_SCHEDULE encrypt_ks;
54 IDEA_KEY_SCHEDULE decrypt_ks;
55 ULONG ivec[2];
56 struct Library *amisslmasterbase;
57 struct Library *amisslbase;
58 LONG amissl_init;
61 BOOL Crypt_Init (struct DiskImagePlugin *Self, const struct PluginData *data);
62 APTR Crypt_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name);
63 void Crypt_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr);
64 LONG Crypt_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg);
65 LONG Crypt_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io);
66 LONG Crypt_Write (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io);
68 struct DiskImagePlugin crypt_plugin = {
69 PLUGIN_NODE(-128, "Crypt"),
70 PLUGIN_FLAG_USERCHOICE|PLUGIN_FLAG_M68K,
72 ZERO,
73 NULL,
74 Crypt_Init,
75 NULL,
76 NULL,
77 Crypt_OpenImage,
78 Crypt_CloseImage,
79 Crypt_Geometry,
80 Crypt_Read,
81 Crypt_Write,
82 NULL,
83 NULL,
84 NULL,
85 NULL
88 struct Library *SysBase;
89 struct Library *DOSBase;
90 static struct DIPluginIFace *IPlugin;
91 #define AmiSSLMasterBase image->amisslmasterbase
92 #define AmiSSLBase image->amisslbase
94 BOOL Crypt_Init (struct DiskImagePlugin *Self, const struct PluginData *data) {
95 SysBase = data->SysBase;
96 DOSBase = data->DOSBase;
97 IPlugin = data->IPlugin;
98 return TRUE;
101 static void TrashMem (void *mem, int len) {
102 memset(mem, 0xDE, len);
103 memset(mem, 0xAD, len);
104 memset(mem, 0xBE, len);
105 memset(mem, 0xEF, len);
108 BOOL Crypt_RequestPassword (struct DiskImagePlugin *Self, struct CryptImage *image) {
109 STRPTR passwd;
111 passwd = IPlugin_RequestPassword(image->unit);
112 if (passwd && strlen(passwd) >= 10) {
113 UBYTE key[16];
114 UBYTE *p1, *p2, *p3, ch;
115 memset(key, 0, 16);
117 p1 = (UBYTE *)passwd;
118 p2 = key;
119 p3 = p2 + sizeof(key);
120 while (ch = *p1++) {
121 *p2++ += ch;
122 if (p2 >= p3) p2 = key;
125 TrashMem(passwd, strlen(passwd)+1);
126 idea_set_encrypt_key(key, &image->encrypt_ks);
127 TrashMem(key, 16);
128 idea_set_decrypt_key(&image->encrypt_ks, &image->decrypt_ks);
130 image->key_valid = TRUE;
132 FreeVec(passwd);
134 return image->key_valid;
137 APTR Crypt_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file,
138 CONST_STRPTR name)
140 LONG done = FALSE;
141 LONG error = NO_ERROR;
142 LONG error_string = NO_ERROR_STRING;
143 IPTR error_args[4] = {0};
144 struct CryptImage *image = NULL;
146 image = AllocVec(sizeof(*image), MEMF_CLEAR);
147 if (!image) {
148 error = ERROR_NO_FREE_STORE;
149 goto error;
151 image->file = file;
152 image->unit = unit;
154 image->amisslmasterbase = OpenLibrary("amisslmaster.library", AMISSLMASTER_MIN_VERSION);
155 if (!image->amisslmasterbase) {
156 error = ERROR_OBJECT_NOT_FOUND;
157 error_string = MSG_REQVER;
158 error_args[0] = (IPTR)"amisslmaster.library";
159 error_args[1] = AMISSLMASTER_MIN_VERSION;
160 error_args[2] = 1;
161 goto error;
163 if (InitAmiSSLMaster(AMISSL_CURRENT_VERSION, FALSE) == FALSE) {
164 error = ERROR_OBJECT_WRONG_TYPE;
165 goto error;
167 image->amisslbase = OpenAmiSSL();
168 if (!image->amisslbase) {
169 error = ERROR_OBJECT_WRONG_TYPE;
170 goto error;
172 image->amissl_init = InitAmiSSLA(NULL);
173 if (image->amissl_init != NO_ERROR) {
174 error = ERROR_OBJECT_WRONG_TYPE;
175 goto error;
178 if (!IsCipherAvailable(CIPHER_IDEA)) {
179 error = ERROR_OBJECT_NOT_FOUND;
180 goto error;
183 image->total_bytes = GetFileSize(file);
184 if (image->total_bytes == -1) {
185 error = IoErr();
186 goto error;
188 image->block_size = 512;
189 image->total_bytes &= ~511;
190 image->total_blocks = image->total_bytes >> 9;
192 image->buffer = AllocVec(image->block_size, MEMF_ANY);
193 if (!image->buffer) {
194 error = ERROR_NO_FREE_STORE;
195 goto error;
198 if (!Crypt_RequestPassword(Self, image)) {
199 error = ERROR_REQUIRED_ARG_MISSING;
200 goto error;
203 done = TRUE;
205 error:
206 if (!done) {
207 if (image) {
208 Plugin_CloseImage(Self, image);
209 image = NULL;
210 } else {
211 Close(file);
213 if (error == NO_ERROR) {
214 error = ERROR_OBJECT_WRONG_TYPE;
215 error_string = MSG_EOF;
217 IPlugin_SetDiskImageErrorA(unit, error, error_string, error_args);
219 return image;
222 void Crypt_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr) {
223 struct CryptImage *image = image_ptr;
224 if (image) {
225 if (image->amisslmasterbase) {
226 if (image->amisslbase) {
227 if (image->amissl_init == NO_ERROR) {
228 CleanupAmiSSLA(NULL);
230 CloseAmiSSL();
232 CloseLibrary(image->amisslmasterbase);
234 FreeVec(image->buffer);
235 Close(image->file);
236 TrashMem(image, sizeof(*image));
237 FreeVec(image);
241 LONG Crypt_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg) {
242 struct CryptImage *image = image_ptr;
243 dg->dg_SectorSize = image->block_size;
244 dg->dg_Heads =
245 dg->dg_TrackSectors =
246 dg->dg_CylSectors = 1;
247 dg->dg_Cylinders =
248 dg->dg_TotalSectors = image->total_blocks;
249 return IOERR_SUCCESS;
252 LONG Crypt_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io) {
253 struct CryptImage *image = image_ptr;
254 UQUAD offset;
255 UBYTE *buffer;
256 ULONG size;
257 BPTR file = image->file;
258 LONG error = IOERR_SUCCESS;
259 LONG status;
261 buffer = io->io_Data;
262 offset = ((UQUAD)io->io_Offset)|((UQUAD)io->io_Actual << 32);
263 size = io->io_Length;
264 io->io_Actual = 0;
266 if (offset & 511) return IOERR_BADADDRESS;
267 if (size & 511) return IOERR_BADLENGTH;
269 if (!ChangeFilePosition(file, offset, OFFSET_BEGINNING)) {
270 return TDERR_SeekError;
273 if (offset + size > image->total_bytes) {
274 size = image->total_bytes - offset;
275 error = IOERR_BADLENGTH;
278 /* read encrypted blocks */
279 status = Read(file, buffer, size);
280 if (status == -1) {
281 return IPlugin_DOS2IOErr(IoErr());
282 } else
283 if (status != size) {
284 return TDERR_NotSpecified;
287 io->io_Actual = size;
288 size >>= 9;
289 while (size--) {
290 /* decrypt block */
291 image->ivec[0] = image->ivec[1] = offset;
292 idea_cbc_encrypt(buffer, buffer, 512,
293 &image->decrypt_ks, (UBYTE *)image->ivec, IDEA_DECRYPT);
295 offset += 512;
296 buffer += 512;
298 return error;
301 LONG Crypt_Write (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io) {
302 struct CryptImage *image = image_ptr;
303 UQUAD offset;
304 UBYTE *buffer;
305 ULONG block, size;
306 BPTR file = image->file;
307 LONG error = IOERR_SUCCESS;
308 LONG status;
310 buffer = io->io_Data;
311 offset = ((UQUAD)io->io_Offset)|((UQUAD)io->io_Actual << 32);
312 size = io->io_Length;
313 io->io_Actual = 0;
315 if (offset & 511) return IOERR_BADADDRESS;
316 if (size & 511) return IOERR_BADLENGTH;
317 block = offset >> 9;
318 size >>= 9;
320 if (!ChangeFilePosition(file, offset, OFFSET_BEGINNING)) {
321 return TDERR_SeekError;
324 if (block + size > image->total_blocks) {
325 size = image->total_blocks - block;
326 error = IOERR_BADLENGTH;
329 while (size--) {
330 /* encrypt block */
331 image->ivec[0] = image->ivec[1] = offset;
332 idea_cbc_encrypt(buffer, image->buffer, 512,
333 &image->encrypt_ks, (UBYTE *)image->ivec, IDEA_ENCRYPT);
335 /* write encrypted block */
336 status = Write(file, image->buffer, 512);
337 if (status != 512) {
338 return IPlugin_DOS2IOErr(IoErr());
341 offset += 512;
342 buffer += 512;
343 io->io_Actual += 512;
345 return error;