1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
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>
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
)
53 IDEA_KEY_SCHEDULE encrypt_ks
;
54 IDEA_KEY_SCHEDULE decrypt_ks
;
56 struct Library
*amisslmasterbase
;
57 struct Library
*amisslbase
;
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
,
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
;
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
) {
111 passwd
= IPlugin_RequestPassword(image
->unit
);
112 if (passwd
&& strlen(passwd
) >= 10) {
114 UBYTE
*p1
, *p2
, *p3
, ch
;
117 p1
= (UBYTE
*)passwd
;
119 p3
= p2
+ sizeof(key
);
122 if (p2
>= p3
) p2
= key
;
125 TrashMem(passwd
, strlen(passwd
)+1);
126 idea_set_encrypt_key(key
, &image
->encrypt_ks
);
128 idea_set_decrypt_key(&image
->encrypt_ks
, &image
->decrypt_ks
);
130 image
->key_valid
= TRUE
;
134 return image
->key_valid
;
137 APTR
Crypt_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
,
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
);
148 error
= ERROR_NO_FREE_STORE
;
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
;
163 if (InitAmiSSLMaster(AMISSL_CURRENT_VERSION
, FALSE
) == FALSE
) {
164 error
= ERROR_OBJECT_WRONG_TYPE
;
167 image
->amisslbase
= OpenAmiSSL();
168 if (!image
->amisslbase
) {
169 error
= ERROR_OBJECT_WRONG_TYPE
;
172 image
->amissl_init
= InitAmiSSLA(NULL
);
173 if (image
->amissl_init
!= NO_ERROR
) {
174 error
= ERROR_OBJECT_WRONG_TYPE
;
178 if (!IsCipherAvailable(CIPHER_IDEA
)) {
179 error
= ERROR_OBJECT_NOT_FOUND
;
183 image
->total_bytes
= GetFileSize(file
);
184 if (image
->total_bytes
== -1) {
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
;
198 if (!Crypt_RequestPassword(Self
, image
)) {
199 error
= ERROR_REQUIRED_ARG_MISSING
;
208 Plugin_CloseImage(Self
, image
);
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
);
222 void Crypt_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
) {
223 struct CryptImage
*image
= image_ptr
;
225 if (image
->amisslmasterbase
) {
226 if (image
->amisslbase
) {
227 if (image
->amissl_init
== NO_ERROR
) {
228 CleanupAmiSSLA(NULL
);
232 CloseLibrary(image
->amisslmasterbase
);
234 FreeVec(image
->buffer
);
236 TrashMem(image
, sizeof(*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
;
245 dg
->dg_TrackSectors
=
246 dg
->dg_CylSectors
= 1;
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
;
257 BPTR file
= image
->file
;
258 LONG error
= IOERR_SUCCESS
;
261 buffer
= io
->io_Data
;
262 offset
= ((UQUAD
)io
->io_Offset
)|((UQUAD
)io
->io_Actual
<< 32);
263 size
= io
->io_Length
;
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
);
281 return IPlugin_DOS2IOErr(IoErr());
283 if (status
!= size
) {
284 return TDERR_NotSpecified
;
287 io
->io_Actual
= size
;
291 image
->ivec
[0] = image
->ivec
[1] = offset
;
292 idea_cbc_encrypt(buffer
, buffer
, 512,
293 &image
->decrypt_ks
, (UBYTE
*)image
->ivec
, IDEA_DECRYPT
);
301 LONG
Crypt_Write (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
) {
302 struct CryptImage
*image
= image_ptr
;
306 BPTR file
= image
->file
;
307 LONG error
= IOERR_SUCCESS
;
310 buffer
= io
->io_Data
;
311 offset
= ((UQUAD
)io
->io_Offset
)|((UQUAD
)io
->io_Actual
<< 32);
312 size
= io
->io_Length
;
315 if (offset
& 511) return IOERR_BADADDRESS
;
316 if (size
& 511) return IOERR_BADLENGTH
;
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
;
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);
338 return IPlugin_DOS2IOErr(IoErr());
343 io
->io_Actual
+= 512;