~ubuntu-branches/ubuntu/natty/libgcrypt11/natty-proposed

« back to all changes in this revision

Viewing changes to random/rndhw.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2009-02-21 13:46:58 UTC
  • mto: (1.1.6 upstream) (2.1.3 squeeze)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20090221134658-855twvcr4ezk2ron
ImportĀ upstreamĀ versionĀ 1.4.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* rndhw.c  - Access to the external random daemon
 
2
 * Copyright (C) 2007  Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of Libgcrypt.
 
5
 *
 
6
 * Libgcrypt is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU Lesser General Public License as
 
8
 * published by the Free Software Foundation; either version 2.1 of
 
9
 * the License, or (at your option) any later version.
 
10
 *
 
11
 * Libgcrypt is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <config.h>
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
 
 
24
#include "types.h"
 
25
#include "g10lib.h"
 
26
#include "rand-internal.h"
 
27
 
 
28
#undef USE_PADLOCK
 
29
#ifdef ENABLE_PADLOCK_SUPPORT
 
30
# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
 
31
# define USE_PADLOCK
 
32
# endif
 
33
#endif /*ENABLE_PADLOCK_SUPPORT*/
 
34
 
 
35
/* Keep track on whether the RNG has problems.  */
 
36
static volatile int rng_failed;
 
37
 
 
38
 
 
39
#ifdef USE_PADLOCK
 
40
static size_t
 
41
poll_padlock (void (*add)(const void*, size_t, enum random_origins),
 
42
              enum random_origins origin, int fast)
 
43
{
 
44
  char buffer[64+8] __attribute__ ((aligned (8)));
 
45
  char *p;
 
46
  unsigned int nbytes, status;
 
47
  
 
48
  /* Peter Gutmann's cryptlib tests again whether the RNG is enabled
 
49
     but we don't do so.  We would have to do this also for our AES
 
50
     implementaion and that is definitely too time consuming.  There
 
51
     would be a race condition anyway.  Thus we assume that the OS
 
52
     does not change the Padlock initialization while a user process
 
53
     is running.  */
 
54
  p = buffer;
 
55
  nbytes = 0;
 
56
  while (nbytes < 64)
 
57
    {
 
58
      asm volatile 
 
59
        ("movl %1, %%edi\n\t"         /* Set buffer.  */
 
60
         "xorl %%edx, %%edx\n\t"      /* Request up to 8 bytes.  */
 
61
         ".byte 0x0f, 0xa7, 0xc0\n\t" /* XSTORE RNG. */
 
62
         "movl %%eax, %0\n"           /* Return the status.  */
 
63
         : "=g" (status)
 
64
         : "g" (p)
 
65
         : "%edx", "%edi", "cc"
 
66
         );
 
67
      if ((status & (1<<6))         /* RNG still enabled.  */
 
68
          && !(status & (1<<13))    /* von Neumann corrector is enabled.  */
 
69
          && !(status & (1<<14))    /* String filter is disabled.  */
 
70
          && !(status & 0x1c00)     /* BIAS voltage at default.  */
 
71
          && (!(status & 0x1f) || (status & 0x1f) == 8) /* Sanity check.  */
 
72
          )
 
73
        {
 
74
          nbytes += (status & 0x1f);
 
75
          if (fast)
 
76
            break; /* Don't get into the loop with the fast flag set.  */
 
77
          p += (status & 0x1f);
 
78
        }
 
79
      else 
 
80
        {
 
81
          /* If there was an error we need to break the loop and
 
82
             record that there is something wrong with the padlock
 
83
             RNG.  */
 
84
          rng_failed = 1;
 
85
          break; 
 
86
        }
 
87
    }
 
88
 
 
89
  if (nbytes)
 
90
    {
 
91
      (*add) (buffer, nbytes, origin);
 
92
      wipememory (buffer, nbytes);
 
93
    }
 
94
  return nbytes;
 
95
}
 
96
#endif /*USE_PADLOCK*/
 
97
 
 
98
 
 
99
int
 
100
_gcry_rndhw_failed_p (void)
 
101
{
 
102
  return rng_failed;
 
103
}
 
104
 
 
105
 
 
106
/* Try to read random from a hardware RNG if a fast one is
 
107
   available.  */
 
108
void
 
109
_gcry_rndhw_poll_fast (void (*add)(const void*, size_t, enum random_origins),
 
110
                       enum random_origins origin)
 
111
{
 
112
  (void)add;
 
113
  (void)origin;
 
114
 
 
115
#ifdef USE_PADLOCK
 
116
  if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG))
 
117
    poll_padlock (add, origin, 1);
 
118
#endif  
 
119
}
 
120
 
 
121
 
 
122
/* Read 64 bytes from a hardware RNG and return the number of bytes
 
123
   actually read.  */
 
124
size_t
 
125
_gcry_rndhw_poll_slow (void (*add)(const void*, size_t, enum random_origins),
 
126
                       enum random_origins origin)
 
127
{
 
128
  size_t nbytes = 0;
 
129
 
 
130
  (void)add;
 
131
  (void)origin;
 
132
 
 
133
#ifdef USE_PADLOCK
 
134
  if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG))
 
135
    nbytes += poll_padlock (add, origin, 0);
 
136
#endif  
 
137
 
 
138
  return nbytes;
 
139
}