used rsa coeff field in OpenPGP secret key payload
[strongswan.git] / src / libstrongswan / plugins / padlock / padlock_rng.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
16 #include "padlock_rng.h"
17
18 typedef struct private_padlock_rng_t private_padlock_rng_t;
19 typedef enum padlock_quality_factor_t padlock_quality_factor_t;
20
21 /**
22 * Padlock RNG quality factors
23 */
24 enum padlock_quality_factor_t {
25 /* Lowest quality: Reads 8 bytes */
26 PADLOCK_QF0 = 0x00,
27 /* Medium quality: Reads 4 bytes */
28 PADLOCK_QF1 = 0x01,
29 /* Better quality: Reads 2 bytes */
30 PADLOCK_QF2 = 0x10,
31 /* Highest quality: Reads 1 byte */
32 PADLOCK_QF3 = 0x11,
33 };
34
35 /**
36 * Private data of an padlock_rng_t object.
37 */
38 struct private_padlock_rng_t {
39
40 /**
41 * Public padlock_rng_t interface.
42 */
43 padlock_rng_t public;
44
45 /**
46 * Padlock quality factor
47 */
48 padlock_quality_factor_t quality;
49 };
50
51 /**
52 * Get bytes from Padlock RNG. buf should have space for (len + 7)
53 */
54 static void rng(char *buf, int len, int quality)
55 {
56 while (len > 0)
57 {
58 int status;
59
60 /* run XSTORE until we have all bytes needed. We do not use REP, as
61 * this should not be performance critical and it's easier this way. */
62 asm volatile (
63 ".byte 0x0F,0xA7,0xC0 \n\t"
64 : "=D"(buf), "=a"(status)
65 : "d"(quality), "D"(buf));
66
67 /* bits[0..4] of status word contains the number of bytes read */
68 len -= status & 0x1F;
69 }
70 }
71
72 /**
73 * Implementation of padlock_rng_t.allocate_bytes.
74 */
75 static void allocate_bytes(private_padlock_rng_t *this, size_t bytes,
76 chunk_t *chunk)
77 {
78 chunk->len = bytes;
79 /* padlock requires some additional bytes */
80 chunk->ptr = malloc(bytes + 7);
81
82 rng(chunk->ptr, chunk->len, this->quality);
83 }
84
85 /**
86 * Implementation of padlock_rng_t.get_bytes.
87 */
88 static void get_bytes(private_padlock_rng_t *this, size_t bytes,
89 u_int8_t *buffer)
90 {
91 chunk_t chunk;
92
93 /* Padlock needs a larger buffer than "bytes", we need a new buffer */
94 allocate_bytes(this, bytes, &chunk);
95 memcpy(buffer, chunk.ptr, bytes);
96 chunk_clear(&chunk);
97 }
98
99 /**
100 * Implementation of padlock_rng_t.destroy.
101 */
102 static void destroy(private_padlock_rng_t *this)
103 {
104 free(this);
105 }
106
107 /*
108 * Described in header.
109 */
110 padlock_rng_t *padlock_rng_create(rng_quality_t quality)
111 {
112 private_padlock_rng_t *this = malloc_thing(private_padlock_rng_t);
113
114 this->public.rng.get_bytes = (void (*) (rng_t *, size_t, u_int8_t*)) get_bytes;
115 this->public.rng.allocate_bytes = (void (*) (rng_t *, size_t, chunk_t*)) allocate_bytes;
116 this->public.rng.destroy = (void (*) (rng_t *))destroy;
117
118 /* map RNG quality to Padlock quality factor */
119 switch (quality)
120 {
121 case RNG_WEAK:
122 this->quality = PADLOCK_QF0;
123 break;
124 case RNG_STRONG:
125 this->quality = PADLOCK_QF1;
126 break;
127 case RNG_TRUE:
128 this->quality = PADLOCK_QF3;
129 break;
130 }
131
132 return &this->public;
133 }
134