summaryrefslogtreecommitdiff
path: root/sdk/recipes/files/openssl/m68k-unknown-amigaos/crypto/rand/rand_amiga.c
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/recipes/files/openssl/m68k-unknown-amigaos/crypto/rand/rand_amiga.c')
-rw-r--r--sdk/recipes/files/openssl/m68k-unknown-amigaos/crypto/rand/rand_amiga.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/sdk/recipes/files/openssl/m68k-unknown-amigaos/crypto/rand/rand_amiga.c b/sdk/recipes/files/openssl/m68k-unknown-amigaos/crypto/rand/rand_amiga.c
new file mode 100644
index 0000000..3c18b7d
--- /dev/null
+++ b/sdk/recipes/files/openssl/m68k-unknown-amigaos/crypto/rand/rand_amiga.c
@@ -0,0 +1,189 @@
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+#include "rand_lcl.h"
+
+#if defined(OPENSSL_SYS_AMIGAOS3) || defined(OPENSSL_SYS_AMIGAOS4)
+#define __USE_INLINE__ 1
+
+#include <proto/exec.h>
+#include <proto/timer.h>
+#include <devices/timer.h>
+
+/* Maximum number of attempts to get a delay of 1 microsecond that is not equal to 0 */
+#define MAX_ATTEMPTS 1000
+
+#ifdef __amigaos4__
+
+#ifdef CreateMsgPort
+#undef CreateMsgPort
+#endif
+#define CreateMsgPort() AllocSysObject(ASOT_PORT,NULL)
+#ifdef DeleteMsgPort
+#undef DeleteMsgPort
+#endif
+#define DeleteMsgPort(msgPort) FreeSysObject(ASOT_PORT,msgPort)
+#ifdef CreateIORequest
+#undef CreateIORequest
+#endif
+#define CreateIORequest(ioReplyPort,size) AllocSysObjectTags(ASOT_IOREQUEST,ASOIOR_ReplyPort,ioReplyPort,ASOIOR_Size,size,TAG_DONE)
+#ifdef DeleteIORequest
+#undef DeleteIORequest
+#endif
+#define DeleteIORequest(ioReq) FreeSysObject(ASOT_IOREQUEST,ioReq)
+
+#else
+
+#define GetInterface(a, b, c, d) 1
+#define DropInterface(x)
+
+/* OS3 has a different but compatible TimeVal definition */
+struct TimeVal
+{
+ ULONG Seconds;
+ ULONG Microseconds;
+};
+
+/* ...and ditto for TimeRequest */
+struct TimeRequest
+{
+ struct IORequest Request;
+ struct TimeVal Time;
+};
+
+#endif /* !__amigaos4__ */
+
+int RAND_poll(void)
+{
+ unsigned char temp_buffer[SHA_DIGEST_LENGTH], data_buffer[SHA_DIGEST_LENGTH];
+ struct MsgPort *port = NULL;
+ double entropy_added = 0;
+ struct TimeRequest *time_request = NULL;
+#ifdef __amigaos4__
+ struct IOStdReq *entropy_request = NULL;
+
+ if ((port = CreateMsgPort())
+ && (entropy_request = (struct IOStdReq *)CreateIORequest(port, sizeof(*entropy_request))))
+ {
+ if (OpenDevice(TIMERNAME, UNIT_ENTROPY, (struct IORequest *)entropy_request, 0) == 0)
+ {
+ while(entropy_added < ENTROPY_NEEDED)
+ {
+ entropy_request->io_Command = TR_READENTROPY;
+ entropy_request->io_Data = &temp_buffer[0];
+ entropy_request->io_Length = sizeof(temp_buffer);
+
+ if (DoIO((struct IORequest *)entropy_request) == 0)
+ {
+ SHA1(&temp_buffer[0], sizeof(temp_buffer), &data_buffer[0]);
+ RAND_add(&data_buffer[0], sizeof(data_buffer), sizeof(data_buffer));
+ entropy_added += sizeof(data_buffer);
+ }
+ else
+ break;
+ }
+
+ CloseDevice((struct IORequest *)entropy_request);
+ }
+ }
+
+ DeleteIORequest((struct IORequest *)entropy_request);
+#endif /* __amigaos4__ */
+
+ /* The following block will be used on "classic" machines. It does not generate
+ * a high degree of randomness, but it does the job since RAND_poll is
+ * called only once by OpenSSL to generate a 32 byte seed.
+ */
+ if (entropy_added < ENTROPY_NEEDED
+ && (port || (port = CreateMsgPort()))
+ && (time_request = (struct TimeRequest *)CreateIORequest(port, sizeof(*time_request))))
+ {
+ if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)time_request, 0) == 0)
+ {
+ #if defined(__amigaos4__)
+ struct TimerIFace *ITimer = NULL;
+ #endif
+ struct Device *TimerBase;
+
+ if ((TimerBase = time_request->Request.io_Device)
+ #if defined(__amigaos4__)
+ && (ITimer = (struct TimerIFace *)GetInterface((struct Library *)TimerBase, "main", 1, NULL))
+ #endif
+ )
+ {
+ struct EClockVal curr_eclock;
+ ULONG prev_ev_lo = 0;
+ struct TimeVal tv;
+ int i, attempt;
+ BOOL aborted;
+
+ ReadEClock(&curr_eclock);
+ aborted = FALSE;
+
+ while(!aborted && entropy_added < ENTROPY_NEEDED)
+ {
+ for(i = 0;
+ !aborted && i < (int)sizeof(temp_buffer) - (int)sizeof(ULONG);
+ i++)
+ {
+ attempt = 0;
+
+ /* Ask for a one microsecond delay and measure the time
+ * the delay actually took.
+ */
+ do
+ {
+ time_request->Request.io_Command = TR_ADDREQUEST;
+ time_request->Time.Seconds = 0;
+ time_request->Time.Microseconds = 1;
+
+ if (DoIO((struct IORequest *)time_request) == 0)
+ {
+ prev_ev_lo = curr_eclock.ev_lo;
+ ReadEClock(&curr_eclock);
+
+ attempt++;
+ }
+ else
+ aborted = TRUE;
+ } while(!aborted && prev_ev_lo == 0 && attempt < MAX_ATTEMPTS);
+
+ if (attempt >= MAX_ATTEMPTS)
+ aborted = TRUE;
+
+ /* Since we are going for randomness, ev_hi is irrelevant */
+ temp_buffer[i] = (unsigned char)(curr_eclock.ev_lo - prev_ev_lo);
+ }
+
+ GetSysTime(&tv);
+
+ if (sizeof(temp_buffer) > sizeof(ULONG))
+ *(ULONG *)&temp_buffer[sizeof(temp_buffer) - sizeof(ULONG)]
+ = tv.Microseconds;
+
+ /* Shuffle the bits around and specify that about
+ * one fourth of it adds to the entropy.
+ */
+ if (!aborted)
+ {
+ SHA1(&temp_buffer[0], sizeof(temp_buffer), &data_buffer[0]);
+ RAND_add(&data_buffer[0], sizeof(data_buffer), (double)sizeof(data_buffer) / 4);
+ entropy_added += sizeof(data_buffer) / 4;
+ }
+ }
+ }
+
+ #if defined(__amigaos4__)
+ DropInterface((struct Interface *)ITimer);
+ #endif
+ CloseDevice((struct IORequest *)time_request);
+ }
+ }
+
+ DeleteIORequest((struct IORequest *)time_request);
+
+ DeleteMsgPort(port);
+
+ return(entropy_added >= ENTROPY_NEEDED);
+}
+
+#endif /* OPENSSL_SYS_AMIGA */