some more internall structure changes
[gnupg.git] / g10 / misc.c
1 /* misc.c -  miscellaneous functions
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
6  * GNUPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GNUPG 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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #if defined(__linux__) && defined(__alpha__)
26   #include <asm/sysinfo.h>
27   #include <asm/unistd.h>
28 #endif
29 #include "util.h"
30 #include "main.h"
31 #include "options.h"
32
33
34 const char *g10m_revision_string(int);
35 const char *g10c_revision_string(int);
36 const char *g10u_revision_string(int);
37
38 volatile void
39 pull_in_libs(void)
40 {
41     g10m_revision_string(0);
42     g10c_revision_string(0);
43     g10u_revision_string(0);
44 }
45
46
47 #if defined(__linux__) && defined(__alpha__)
48 #warning using trap_unaligned
49 static int
50 setsysinfo(unsigned long op, void *buffer, unsigned long size,
51                      int *start, void *arg, unsigned long flag)
52 {
53     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
54 }
55
56 void
57 trap_unaligned(void)
58 {
59     unsigned int buf[2];
60
61     buf[0] = SSIN_UACPROC;
62     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
63     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
64 }
65 #else
66 void
67 trap_unaligned(void)
68 {  /* dummy */
69 }
70 #endif
71
72
73 u16
74 checksum_u16( unsigned n )
75 {
76     u16 a;
77
78     a  = (n >> 8) & 0xff;
79     if( opt.emulate_bugs & 1 ) {
80        a |= n & 0xff;
81        log_debug("csum_u16 emulated for n=%u\n", n);
82     }
83     else
84        a += n & 0xff;
85     return a;
86 }
87
88 static u16
89 checksum_u16_nobug( unsigned n )
90 {
91     u16 a;
92
93     a  = (n >> 8) & 0xff;
94     a += n & 0xff;
95     return a;
96 }
97
98 u16
99 checksum( byte *p, unsigned n )
100 {
101     u16 a;
102
103     for(a=0; n; n-- )
104         a += *p++;
105     return a;
106 }
107
108 u16
109 checksum_mpi( MPI a )
110 {
111     u16 csum;
112     byte *buffer;
113     unsigned nbytes;
114     unsigned nbits;
115
116     buffer = mpi_get_buffer( a, &nbytes, NULL );
117     /* some versions of gpg encode wrong values for the length of an mpi
118      * so that mpi_get_nbits() which counts the mpi yields another (shorter)
119      * value than the one store with the mpi.  mpi_get_nbit_info() returns
120      * this stored value if it is still available.
121      */
122
123     if( opt.emulate_bugs & 1 )
124         nbits = 0;
125     else
126         nbits = mpi_get_nbit_info(a);
127     if( !nbits )
128        nbits = mpi_get_nbits(a);
129     csum = checksum_u16( nbits );
130     csum += checksum( buffer, nbytes );
131     m_free( buffer );
132     return csum;
133 }
134
135 /****************
136  * This is the correct function
137  */
138 u16
139 checksum_mpi_counted_nbits( MPI a )
140 {
141     u16 csum;
142     byte *buffer;
143     unsigned nbytes;
144     unsigned nbits;
145
146     buffer = mpi_get_buffer( a, &nbytes, NULL );
147     nbits = mpi_get_nbits(a);
148     mpi_set_nbit_info(a,nbits);
149     csum = checksum_u16_nobug( nbits );
150     csum += checksum( buffer, nbytes );
151     m_free( buffer );
152     return csum;
153 }
154