#
source:
trunk/third/ssh/idea.c
@
12646

Revision 12646, 5.9 KB checked in by danw, 26 years ago (diff) |
---|

Line | |
---|---|

1 | /* |

2 | |

3 | idea.c |

4 | |

5 | Author: Tatu Ylonen <ylo@cs.hut.fi> |

6 | |

7 | Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |

8 | All rights reserved |

9 | |

10 | Created: Sun Jun 25 02:59:39 1995 ylo |

11 | |

12 | This code is based on Xuejia Lai: On the Design and Security of Block |

13 | Ciphers, ETH Series in Information Processing, vol. 1, Hartung-Gorre |

14 | Verlag, Konstanz, Switzerland, 1992. Another source was Bruce |

15 | Schneier: Applied Cryptography, John Wiley & Sons, 1994. |

16 | |

17 | The IDEA mathematical formula may be covered by one or more of the |

18 | following patents: PCT/CH91/00117, EP 0 482 154 B1, US Pat. 5,214,703. |

19 | |

20 | */ |

21 | |

22 | /* |

23 | * $Id: idea.c,v 1.1.1.2 1999-03-08 17:43:10 danw Exp $ |

24 | * $Log: not supported by cvs2svn $ |

25 | * Revision 1.1.1.1 1996/02/18 21:38:11 ylo |

26 | * Imported ssh-1.2.13. |

27 | * |

28 | * Revision 1.3 1995/09/13 11:55:48 ylo |

29 | * Minor changes to make it work on Cray. |

30 | * |

31 | * Revision 1.2 1995/07/13 01:24:44 ylo |

32 | * Removed "Last modified" header. |

33 | * Added cvs log. |

34 | * |

35 | * $Endlog$ |

36 | */ |

37 | |

38 | #include "includes.h" |

39 | #include "getput.h" |

40 | #include "idea.h" |

41 | |

42 | /* Sets idea key for encryption. */ |

43 | |

44 | void idea_set_key(IDEAContext *c, const unsigned char key[16]) |

45 | { |

46 | int i; |

47 | word16 *keys; |

48 | |

49 | /* Get pointer to the keys. */ |

50 | keys = c->key_schedule; |

51 | |

52 | /* Keys for the first round are directly taken from the user-supplied key. */ |

53 | for (i = 0; i < 8; i++) |

54 | keys[i] = GET_16BIT(key + 2 * i); |

55 | |

56 | /* Each round uses the key of the previous key, rotated to the left by 25 |

57 | bits. The last four keys (output transform) are the first four keys |

58 | from what would be the ninth round. */ |

59 | for (i = 8; i < 52; i++) |

60 | { |

61 | if ((i & 7) == 0) |

62 | keys += 8; |

63 | keys[i & 7] = ((keys[((i + 1) & 7) - 8] << 9) | |

64 | (keys[((i + 2) & 7) - 8] >> 7)) & 0xffff; |

65 | } |

66 | } |

67 | |

68 | /* Destroys any sensitive data in the context. */ |

69 | |

70 | void idea_destroy_context(IDEAContext *c) |

71 | { |

72 | memset(&c, 0, sizeof(c)); |

73 | } |

74 | |

75 | /* Performs the "multiplication" operation of IDEA: returns a*b mod 65537, |

76 | where a and b are first converted to 65536 if they are zero, and result |

77 | 65536 is converted to zero. Both inputs should be less than 65536. |

78 | Only the lower 16 bits of result are significant; other bits are garbage. |

79 | */ |

80 | |

81 | static inline word32 mulop(word32 a, word32 b) |

82 | { |

83 | word32 ab = a * b; |

84 | if (ab != 0) |

85 | { |

86 | word32 lo = ab & 0xffff; |

87 | word32 hi = (ab >> 16) & 0xffff; |

88 | return (lo - hi) + (lo < hi); |

89 | } |

90 | if (a == 0) |

91 | return 1 - b; |

92 | return 1 - a; |

93 | } |

94 | |

95 | /* Performs the IDEA cipher transform on a block of data. */ |

96 | |

97 | void idea_transform(IDEAContext *c, word32 l, word32 r, word32 *output) |

98 | { |

99 | unsigned int round; |

100 | word16 *keys; |

101 | word32 t1, t2, x1, x2, x3, x4; |

102 | |

103 | keys = c->key_schedule; |

104 | x1 = l >> 16; |

105 | x2 = l; |

106 | x3 = r >> 16; |

107 | x4 = r; |

108 | for (round = 0; round < 8; round++) |

109 | { |

110 | x1 = mulop(x1 & 0xffff, keys[0]); |

111 | x3 = x3 + keys[2]; |

112 | x4 = mulop(x4 & 0xffff, keys[3]); |

113 | x2 = x2 + keys[1]; |

114 | t1 = x1 ^ x3; |

115 | t2 = x2 ^ x4; |

116 | t1 = mulop(t1 & 0xffff, keys[4]); |

117 | t2 = t1 + t2; |

118 | t2 = mulop(t2 & 0xffff, keys[5]); |

119 | t1 = t1 + t2; |

120 | x1 = x1 ^ t2; |

121 | x4 = x4 ^ t1; |

122 | t1 = t1 ^ x2; |

123 | x2 = t2 ^ x3; |

124 | x3 = t1; |

125 | keys += 6; |

126 | } |

127 | |

128 | x1 = mulop(x1 & 0xffff, keys[0]); |

129 | x3 = (x2 + keys[2]) & 0xffff; |

130 | x2 = t1 + keys[1]; /* t1 == old x3 */ |

131 | x4 = mulop(x4 & 0xffff, keys[3]); |

132 | output[0] = (x1 << 16) | (x2 & 0xffff); |

133 | output[1] = (x3 << 16) | (x4 & 0xffff); |

134 | } |

135 | |

136 | /* Encrypts len bytes from src to dest in CFB mode. Len need not be a multiple |

137 | of 8; if it is not, iv at return will contain garbage. |

138 | Otherwise, iv will be modified at end to a value suitable for continuing |

139 | encryption. */ |

140 | |

141 | void idea_cfb_encrypt(IDEAContext *c, unsigned char *iv, unsigned char *dest, |

142 | const unsigned char *src, unsigned int len) |

143 | { |

144 | word32 iv0, iv1, out[2]; |

145 | unsigned int i; |

146 | |

147 | iv0 = GET_32BIT(iv); |

148 | iv1 = GET_32BIT(iv + 4); |

149 | |

150 | for (i = 0; i < len; i += 8) |

151 | { |

152 | idea_transform(c, iv0, iv1, out); |

153 | iv0 = out[0] ^ GET_32BIT(src + i); |

154 | iv1 = out[1] ^ GET_32BIT(src + i + 4); |

155 | if (i + 8 <= len) |

156 | { |

157 | PUT_32BIT(dest + i, iv0); |

158 | PUT_32BIT(dest + i + 4, iv1); |

159 | } |

160 | else |

161 | { |

162 | switch (len - i) |

163 | { |

164 | case 7: |

165 | dest[i + 6] = iv1 >> 8; |

166 | /*FALLTHROUGH*/ |

167 | case 6: |

168 | dest[i + 5] = iv1 >> 16; |

169 | /*FALLTHROUGH*/ |

170 | case 5: |

171 | dest[i + 4] = iv1 >> 24; |

172 | /*FALLTHROUGH*/ |

173 | case 4: |

174 | dest[i + 3] = iv0; |

175 | /*FALLTHROUGH*/ |

176 | case 3: |

177 | dest[i + 2] = iv0 >> 8; |

178 | /*FALLTHROUGH*/ |

179 | case 2: |

180 | dest[i + 1] = iv0 >> 16; |

181 | /*FALLTHROUGH*/ |

182 | case 1: |

183 | dest[i] = iv0 >> 24; |

184 | /*FALLTHROUGH*/ |

185 | } |

186 | } |

187 | } |

188 | PUT_32BIT(iv, iv0); |

189 | PUT_32BIT(iv + 4, iv1); |

190 | } |

191 | |

192 | /* Decrypts len bytes from src to dest in CFB mode. Len need not be a multiple |

193 | of 8; if it is not, iv at return will contain garbage. |

194 | Otherwise, iv will be modified at end to a value suitable for continuing |

195 | decryption. */ |

196 | |

197 | void idea_cfb_decrypt(IDEAContext *c, unsigned char *iv, unsigned char *dest, |

198 | const unsigned char *src, unsigned int len) |

199 | { |

200 | word32 iv0, iv1, out[2], plain0, plain1; |

201 | unsigned int i; |

202 | |

203 | iv0 = GET_32BIT(iv); |

204 | iv1 = GET_32BIT(iv + 4); |

205 | |

206 | for (i = 0; i < len; i += 8) |

207 | { |

208 | idea_transform(c, iv0, iv1, out); |

209 | iv0 = GET_32BIT(src + i); |

210 | iv1 = GET_32BIT(src + i + 4); |

211 | plain0 = out[0] ^ iv0; |

212 | plain1 = out[1] ^ iv1; |

213 | if (i + 8 <= len) |

214 | { |

215 | PUT_32BIT(dest + i, plain0); |

216 | PUT_32BIT(dest + i + 4, plain1); |

217 | } |

218 | else |

219 | { |

220 | switch (len - i) |

221 | { |

222 | case 7: |

223 | dest[i + 6] = plain1 >> 8; |

224 | /*FALLTHROUGH*/ |

225 | case 6: |

226 | dest[i + 5] = plain1 >> 16; |

227 | /*FALLTHROUGH*/ |

228 | case 5: |

229 | dest[i + 4] = plain1 >> 24; |

230 | /*FALLTHROUGH*/ |

231 | case 4: |

232 | dest[i + 3] = plain0; |

233 | /*FALLTHROUGH*/ |

234 | case 3: |

235 | dest[i + 2] = plain0 >> 8; |

236 | /*FALLTHROUGH*/ |

237 | case 2: |

238 | dest[i + 1] = plain0 >> 16; |

239 | /*FALLTHROUGH*/ |

240 | case 1: |

241 | dest[i] = plain0 >> 24; |

242 | /*FALLTHROUGH*/ |

243 | } |

244 | } |

245 | } |

246 | PUT_32BIT(iv, iv0); |

247 | PUT_32BIT(iv + 4, iv1); |

248 | } |

**Note:**See TracBrowser for help on using the repository browser.