]>
Commit | Line | Data |
---|---|---|
bd940221 | 1 | /* R_DH.C - Diffie-Hellman routines for RSAREF |
2 | */ | |
3 | ||
4 | /* Copyright (C) RSA Laboratories, a division of RSA Data Security, | |
5 | Inc., created 1993. All rights reserved. | |
6 | */ | |
7 | ||
8 | #include "global.h" | |
9 | #include "rsaref.h" | |
10 | #include "r_random.h" | |
11 | #include "nn.h" | |
12 | #include "prime.h" | |
13 | ||
14 | /* Generates Diffie-Hellman parameters. | |
15 | */ | |
16 | int R_GenerateDHParams (params, primeBits, subPrimeBits, randomStruct) | |
17 | R_DH_PARAMS *params; /* new Diffie-Hellman parameters */ | |
18 | unsigned int primeBits; /* length of prime in bits */ | |
19 | unsigned int subPrimeBits; /* length of subprime in bits */ | |
20 | R_RANDOM_STRUCT *randomStruct; /* random structure */ | |
21 | { | |
22 | int status; | |
23 | NN_DIGIT g[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS], | |
24 | t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS]; | |
25 | unsigned int pDigits; | |
26 | ||
27 | pDigits = (primeBits + NN_DIGIT_BITS - 1) / NN_DIGIT_BITS; | |
28 | ||
29 | /* Generate subprime q between 2^(subPrimeBits-1) and | |
30 | 2^subPrimeBits-1, searching in steps of 2. | |
31 | */ | |
32 | NN_Assign2Exp (t, subPrimeBits-1, pDigits); | |
33 | NN_Assign (u, t, pDigits); | |
34 | NN_ASSIGN_DIGIT (v, 1, pDigits); | |
35 | NN_Sub (v, t, v, pDigits); | |
36 | NN_Add (u, u, v, pDigits); | |
37 | NN_ASSIGN_DIGIT (v, 2, pDigits); | |
38 | if (status = GeneratePrime (q, t, u, v, pDigits, randomStruct)) | |
39 | return (status); | |
40 | ||
41 | /* Generate prime p between 2^(primeBits-1) and 2^primeBits-1, | |
42 | searching in steps of 2*q. | |
43 | */ | |
44 | NN_Assign2Exp (t, primeBits-1, pDigits); | |
45 | NN_Assign (u, t, pDigits); | |
46 | NN_ASSIGN_DIGIT (v, 1, pDigits); | |
47 | NN_Sub (v, t, v, pDigits); | |
48 | NN_Add (u, u, v, pDigits); | |
49 | NN_LShift (v, q, 1, pDigits); | |
50 | if (status = GeneratePrime (p, t, u, v, pDigits, randomStruct)) | |
51 | return (status); | |
52 | ||
53 | /* Generate generator g for subgroup as 2^((p-1)/q) mod p. | |
54 | */ | |
55 | NN_ASSIGN_DIGIT (g, 2, pDigits); | |
56 | NN_Div (t, u, p, pDigits, q, pDigits); | |
57 | NN_ModExp (g, g, t, pDigits, p, pDigits); | |
58 | ||
59 | params->generatorLen = params->primeLen = DH_PRIME_LEN (primeBits); | |
60 | NN_Encode (params->prime, params->primeLen, p, pDigits); | |
61 | NN_Encode (params->generator, params->generatorLen, g, pDigits); | |
62 | ||
63 | return (0); | |
64 | } | |
65 | ||
66 | /* Sets up Diffie-Hellman key agreement. Public value has same length | |
67 | as prime. | |
68 | */ | |
69 | int R_SetupDHAgreement | |
70 | (publicValue, privateValue, privateValueLen, params, randomStruct) | |
71 | unsigned char *publicValue; /* new public value */ | |
72 | unsigned char *privateValue; /* new private value */ | |
73 | unsigned int privateValueLen; /* length of private value */ | |
74 | R_DH_PARAMS *params; /* Diffie-Hellman parameters */ | |
75 | R_RANDOM_STRUCT *randomStruct; /* random structure */ | |
76 | { | |
77 | int status; | |
78 | NN_DIGIT g[MAX_NN_DIGITS], p[MAX_NN_DIGITS], x[MAX_NN_DIGITS], | |
79 | y[MAX_NN_DIGITS]; | |
80 | unsigned int pDigits, xDigits; | |
81 | ||
82 | NN_Decode (p, MAX_NN_DIGITS, params->prime, params->primeLen); | |
83 | pDigits = NN_Digits (p, MAX_NN_DIGITS); | |
84 | NN_Decode (g, pDigits, params->generator, params->generatorLen); | |
85 | ||
86 | /* Generate private value. | |
87 | */ | |
88 | if (status = R_GenerateBytes (privateValue, privateValueLen, randomStruct)) | |
89 | return (status); | |
90 | NN_Decode (x, pDigits, privateValue, privateValueLen); | |
91 | xDigits = NN_Digits (x, pDigits); | |
92 | ||
93 | /* Compute y = g^x mod p. | |
94 | */ | |
95 | NN_ModExp (y, g, x, xDigits, p, pDigits); | |
96 | ||
97 | NN_Encode (publicValue, params->primeLen, y, pDigits); | |
98 | ||
99 | /* Zeroize sensitive information. | |
100 | */ | |
101 | R_memset ((POINTER)x, 0, sizeof (x)); | |
102 | ||
103 | return (0); | |
104 | } | |
105 | ||
106 | /* Computes agreed key from the other party's public value, a private | |
107 | value, and Diffie-Hellman parameters. Other public value and | |
108 | agreed-upon key have same length as prime. | |
109 | ||
110 | Requires otherPublicValue < prime. | |
111 | */ | |
112 | int R_ComputeDHAgreedKey | |
113 | (agreedKey, otherPublicValue, privateValue, privateValueLen, params) | |
114 | unsigned char *agreedKey; /* new agreed key */ | |
115 | unsigned char *otherPublicValue; /* other's public value */ | |
116 | unsigned char *privateValue; /* private value */ | |
117 | unsigned int privateValueLen; /* length of private value */ | |
118 | R_DH_PARAMS *params; /* Diffie-Hellman parameters */ | |
119 | { | |
120 | NN_DIGIT p[MAX_NN_DIGITS], x[MAX_NN_DIGITS], y[MAX_NN_DIGITS], | |
121 | z[MAX_NN_DIGITS]; | |
122 | unsigned int pDigits, xDigits; | |
123 | ||
124 | NN_Decode (p, MAX_NN_DIGITS, params->prime, params->primeLen); | |
125 | pDigits = NN_Digits (p, MAX_NN_DIGITS); | |
126 | NN_Decode (x, pDigits, privateValue, privateValueLen); | |
127 | xDigits = NN_Digits (x, pDigits); | |
128 | NN_Decode (y, pDigits, otherPublicValue, params->primeLen); | |
129 | ||
130 | if (NN_Cmp (y, p, pDigits) >= 0) | |
131 | return (RE_DATA); | |
132 | ||
133 | /* Compute z = y^x mod p. | |
134 | */ | |
135 | NN_ModExp (z, y, x, xDigits, p, pDigits); | |
136 | ||
137 | NN_Encode (agreedKey, params->primeLen, z, pDigits); | |
138 | ||
139 | /* Zeroize sensitive information. | |
140 | */ | |
141 | R_memset ((POINTER)x, 0, sizeof (x)); | |
142 | R_memset ((POINTER)z, 0, sizeof (z)); | |
143 | ||
144 | return (0); | |
145 | } |