rsaglue.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /*
  2. * Copyright (c) 1995 Colin Plumb. All rights reserved.
  3. * For licensing and other legal details, see the file legal.c.
  4. *
  5. * rsaglue.c - The interface between bignum math and RSA operations.
  6. * This layer's primary reason for existence is to allow adaptation
  7. * to other RSA math libraries for legal reasons.
  8. */
  9. #include "first.h"
  10. #include "bn.h"
  11. #include "keys.h"
  12. #include "random.h"
  13. #include "rsaglue.h"
  14. #include "usuals.h"
  15. /*#define BNDEBUG 1*/
  16. #if BNDEBUG
  17. /* Some debugging hooks which have been left in for now. */
  18. #include "bn/bnprint.h"
  19. #define bndPut(prompt, bn) bnPrint(stdout, prompt, bn, "\n")
  20. #define bndPrintf printf
  21. #else
  22. #define bndPut(prompt, bn) ((void)(prompt),(void)(bn))
  23. #define bndPrintf(x) (void)0
  24. #endif
  25. /*
  26. * This returns TRUE if the key is too big, returning the
  27. * maximum number of bits that the library can accept. It
  28. * is used if you want to use something icky from RSADSI, whose
  29. * code is known to have satatic limits on key sizes. (BSAFE 2.1
  30. * advertises 2048-bit key sizes. It lies. It's talking about
  31. * conventional RC4 keys, whicah are useless to make anything like
  32. * that large. RSA keys are limited to 1024 bits.
  33. */
  34. int
  35. rsaKeyTooBig(struct PubKey const *pub, struct SecKey const *sec)
  36. {
  37. (void)pub;
  38. (void)sec;
  39. return 0; /* Never too big! */
  40. }
  41. /*
  42. * Fill the given bignum, from bytes high-1 through low (where 0 is
  43. * the least significant byte), with non-zero random data.
  44. */
  45. static int
  46. randomPad(struct BigNum *bn, unsigned high, unsigned low)
  47. {
  48. unsigned i, l;
  49. byte padding[64]; /* This can be any size (>0) whatsoever */
  50. high -= low;
  51. while (high) {
  52. l = high < sizeof(padding) ? high : sizeof(padding);
  53. randBytes(padding, l);
  54. for (i = 0; i < l; i++) { /* Replace all zero bytes */
  55. while(padding[i] == 0)
  56. randBytes(padding+i, 1);
  57. }
  58. high -= l;
  59. if (bnInsertBigBytes(bn, padding, high+low, l) < 0)
  60. return RSAGLUE_NOMEM;
  61. }
  62. memset(padding, 0, sizeof(padding));
  63. return 0;
  64. }
  65. /*
  66. * Fill the given bignum, from bytes high-1 through low (where 0 is
  67. * the least significant byte), with all ones (0xFF) data.
  68. */
  69. static int
  70. onesPad(struct BigNum *bn, unsigned high, unsigned low)
  71. {
  72. unsigned l;
  73. static byte const padding[] = {
  74. 255,255,255,255,255,255,255,255,
  75. 255,255,255,255,255,255,255,255
  76. };
  77. high -= low;
  78. while (high) {
  79. l = high < sizeof(padding) ? high : sizeof(padding);
  80. high -= l;
  81. if (bnInsertBigBytes(bn, padding, high+low, l) < 0)
  82. return RSAGLUE_NOMEM;
  83. }
  84. return 0;
  85. }
  86. /*
  87. * Wrap a PKCS type 2 wrapper around some data and RSA encrypt it.
  88. * If the modulus is n bytes long, with the most significant byte
  89. * being n-1 and the least significant, 0, the wrapper looks like:
  90. *
  91. * Position Value Function
  92. * n-1 0 This is needed to ensure that the padded number
  93. * is less than the modulus.
  94. * n-2 2 The padding type (non-zero random).
  95. * n-3..len+1 ??? Non-zero random padding bytes to "salt" the
  96. * output and prevent duplicate plaintext attacks.
  97. * len 0 Zero byte to mark the end of the padding
  98. * len-1..0 data Supplied payload data.
  99. *
  100. * There really should be several bytes of padding, although this
  101. * routine will not fail to encrypt unless it will not fit, even
  102. * with no padding bytes.
  103. */
  104. static byte const encryptedType = 2;
  105. int
  106. rsaPublicEncrypt(struct BigNum *bn, byte const *in, unsigned len,
  107. struct PubKey const *pub)
  108. {
  109. unsigned bytes = (bnBits(&pub->n)+7)/8;
  110. if (len+3 > bytes)
  111. return RSAGLUE_TOOSMALL; /* Won't fit! */
  112. /* Set the entire number to 0 to start */
  113. (void)bnSetQ(bn, 0);
  114. if (bnInsertBigBytes(bn, &encryptedType, bytes-2, 1) < 0)
  115. return RSAGLUE_NOMEM;
  116. if (randomPad(bn, bytes-2, len+1) < 0)
  117. return RSAGLUE_NOMEM;
  118. if (bnInsertBigBytes(bn, in, 0, len) < 0)
  119. return RSAGLUE_NOMEM;
  120. bndPrintf("RSA encrypting.\n");
  121. bndPut("plaintext = ", bn);
  122. return bnExpMod(bn, bn, &pub->e, &pub->n);
  123. }
  124. /*
  125. * This performs a modular exponentiation using the Chinese Remainder
  126. * Algorithm when the modulus is known to have two relatively prime
  127. * factors n = p * q, and u = p^-1 (mod q) has been precomputed.
  128. *
  129. * The chinese remainder algorithm lets a computation mod n be performed
  130. * mod p and mod q, and the results combined. Since it takes
  131. * (considerably) more than twice as long to perform modular exponentiation
  132. * mod n as it does to perform it mod p and mod q, time is saved.
  133. *
  134. * If x is the desired result, let xp and xq be the values of x mod p
  135. * and mod q, respectively. Obviously, x = xp + p * k for some k.
  136. * Taking this mod q, xq == xp + p*k (mod q), so p*k == xq-xp (mod q)
  137. * and k == p^-1 * (xq-xp) (mod q), so k = u * (xq-xp mod q) mod q.
  138. * After that, x = xp + p * k.
  139. *
  140. * Another savings comes from reducing the exponent d modulo phi(p)
  141. * and phi(q). Here, we assume that p and q are prime, so phi(p) = p-1
  142. * and phi(q) = q-1.
  143. */
  144. static int
  145. bnExpModCRA(struct BigNum *x, struct BigNum const *d,
  146. struct BigNum const *p, struct BigNum const *q, struct BigNum const *u)
  147. {
  148. struct BigNum xp, xq, k;
  149. int i;
  150. bndPrintf("Performing CRA\n");
  151. bndPut("x = ", x);
  152. bndPut("p = ", p);
  153. bndPut("q = ", q);
  154. bndPut("d = ", d);
  155. bndPut("u = ", u);
  156. bnBegin(&xp);
  157. bnBegin(&xq);
  158. bnBegin(&k);
  159. /* Compute xp = (x mod p) ^ (d mod p-1) mod p */
  160. if (bnCopy(&xp, p) < 0) /* First, use xp to hold p-1 */
  161. goto fail;
  162. (void)bnSubQ(&xp, 1); /* p > 1, so subtracting is safe. */
  163. if (bnMod(&k, d, &xp) < 0) /* Use k to hold the exponent */
  164. goto fail;
  165. bndPut("d mod p-1 = ", &k);
  166. if (bnMod(&xp, x, p) < 0) /* Now xp = (x mod p) */
  167. goto fail;
  168. bndPut("x mod p = ", &xp);
  169. if (bnExpMod(&xp, &xp, &k, p) < 0) /* xp = (x mod p)^k mod p */
  170. goto fail;
  171. bndPut("xp = x^d mod p = ", &xp);
  172. /* Compute xq = (x mod q) ^ (d mod q-1) mod q */
  173. if (bnCopy(&xq, q) < 0) /* First, use xq to hold q-1 */
  174. goto fail;
  175. (void)bnSubQ(&xq, 1); /* q > 1, so subtracting is safe. */
  176. if (bnMod(&k, d, &xq) < 0) /* Use k to hold the exponent */
  177. goto fail;
  178. bndPut("d mod q-1 = ", &k);
  179. if (bnMod(&xq, x, q) < 0) /* Now xq = (x mod q) */
  180. goto fail;
  181. bndPut("x mod q = ", &xq);
  182. if (bnExpMod(&xq, &xq, &k, q) < 0) /* xq = (x mod q)^k mod q */
  183. goto fail;
  184. bndPut("xq = x^d mod q = ", &xq);
  185. i = bnSub(&xq, &xp);
  186. bndPut("xq - xp = ", &xq);
  187. bndPrintf(("With sign %d\n", i));
  188. if (i < 0)
  189. goto fail;
  190. if (i) {
  191. /*
  192. * Borrow out - xq-xp is negative, so bnSub returned
  193. * xp-xq instead, the negative of the true answer.
  194. * Add q back (which is subtracting from the negative)
  195. * until the sign flips again. If p is much greater
  196. * than q, this step could take annoyingly long.
  197. * PGP requires that p < q, so it'll only happen once.
  198. * You could get this stuck in a very lengthy loop by
  199. * feeding this function a p >> q, but it seems fair
  200. * to assume that secret keys are not constructed
  201. * maliciously.
  202. *
  203. * If this becomes a concern, you can fix it up with a
  204. * bnMod. (But watch out for the case that the correct
  205. * answer is zero!)
  206. */
  207. do {
  208. i = bnSub(&xq, q);
  209. bndPut("xq - xp mod q = ", &xq);
  210. if (i < 0)
  211. goto fail;
  212. } while (!i);
  213. }
  214. /* Compute k = xq * u mod q */
  215. if (bnMul(&k, u, &xq) < 0)
  216. goto fail;
  217. bndPut("(xq-xp) * u = ", &k);
  218. if (bnMod(&k, &k, q) < 0)
  219. goto fail;
  220. bndPut("k = (xq-xp)*u % q = ", &k);
  221. #if BNDEBUG /* @@@ DEBUG - do it the slow way for comparison */
  222. if (bnMul(&xq, p, q) < 0)
  223. goto fail;
  224. bndPut("n = p*q = ", &xq);
  225. if (bnExpMod(x, x, d, &xq) < 0)
  226. goto fail;
  227. if (bnCopy(&xq, x) < 0)
  228. goto fail;
  229. bndPut("x^d mod n = ", &xq);
  230. #endif
  231. /* Now x = k * p + xp is the final answer */
  232. if (bnMul(x, &k, p) < 0)
  233. goto fail;
  234. bndPut("k * p = ", x);
  235. if (bnAdd(x, &xp) < 0)
  236. goto fail;
  237. bndPut("k*p + xp = ", x);
  238. #if BNDEBUG
  239. if (bnCmp(x, &xq) != 0) {
  240. bndPrintf(("Nasty!!!\n"));
  241. goto fail;
  242. }
  243. bnSetQ(&k, 17);
  244. bnMul(&xp, p, q);
  245. bnExpMod(&xq, &xq, &k, &xp);
  246. bndPut("x^17 mod n = ", &xq);
  247. #endif
  248. bnEnd(&xp);
  249. bnEnd(&xq);
  250. bnEnd(&k);
  251. return 0;
  252. fail:
  253. bnEnd(&xp);
  254. bnEnd(&xq);
  255. bnEnd(&k);
  256. return RSAGLUE_NOMEM;
  257. }
  258. /*
  259. * This does an RSA signing operation, which is very similar, except
  260. * that the padding differs. The type is 1, and the padding is all 1's
  261. * (hex 0xFF).
  262. *
  263. * To summarize, the format is:
  264. *
  265. * Position Value Function
  266. * n-1 0 This is needed to ensure that the padded number
  267. * is less than the modulus.
  268. * n-2 1 The padding type (all ones).
  269. * n-3..len+1 255 All ones padding to ensure signatures are rare.
  270. * len 0 Zero byte to mark the end of the padding
  271. * len-1..0 data The payload
  272. *
  273. *
  274. * The reason for the all 1's padding is an extra consistency check.
  275. * A randomly invented signature will not decrypt to have the long
  276. * run of ones necessary for acceptance.
  277. *
  278. * Oh... the public key isn't needed to decrypt, but it's passed in
  279. * because a different glue library may need it for some reason.
  280. */
  281. static const byte signedType = 1;
  282. int
  283. rsaPrivateEncrypt(struct BigNum *bn, byte const *in, unsigned len,
  284. struct PubKey const *pub, struct SecKey const *sec)
  285. {
  286. unsigned bytes = (bnBits(&pub->n)+7)/8;
  287. /* Set the entire number to 0 to start */
  288. (void)bnSetQ(bn, 0);
  289. if (len+3 > bytes)
  290. return RSAGLUE_TOOSMALL; /* Won't fit */
  291. if (bnInsertBigBytes(bn, &signedType, bytes-2, 1) < 0)
  292. return RSAGLUE_NOMEM;
  293. if (onesPad(bn, bytes-2, len+1) < 0)
  294. return RSAGLUE_NOMEM;
  295. if (bnInsertBigBytes(bn, in, 0, len) < 0)
  296. return RSAGLUE_NOMEM;
  297. bndPrintf(("RSA signing.\n"));
  298. bndPut("plaintext = ", bn);
  299. return bnExpModCRA(bn, &sec->d, &sec->p, &sec->q, &sec->u);
  300. }
  301. /*
  302. * Searches bytes, beginning with start-1 and progressing to 0,
  303. * until one that is not 0xff is found. The idex of the last 0xff
  304. * byte is returned (or start if start-1 is not 0xff.)
  305. */
  306. static unsigned
  307. bnSearchNonOneFromHigh(struct BigNum const *bn, unsigned start)
  308. {
  309. byte buf[16]; /* Size is arbitrary */
  310. unsigned l;
  311. unsigned i;
  312. while (start) {
  313. l = start < sizeof(buf) ? start : sizeof(buf);
  314. start -= l;
  315. bnExtractBigBytes(bn, buf, start, l);
  316. for (i = 0; i < l; i++) {
  317. if (buf[i] != 0xff) {
  318. memset(buf, 0, sizeof(buf));
  319. return start + l - i;
  320. }
  321. }
  322. }
  323. /* Nothing found */
  324. memset(buf, 0, sizeof(buf));
  325. return 0;
  326. }
  327. /*
  328. * Decrypt a message with a public key.
  329. * These destroy (actually, replace with a decrypted version) the
  330. * input bignum bn.
  331. *
  332. * Performs an RSA signature check. Returns a prefix of the unwrapped
  333. * data in the given buf. Returns the length of the untruncated
  334. * data, which may exceed "len". Returns <0 on error.
  335. */
  336. int
  337. rsaPublicDecrypt(byte *buf, unsigned len, struct BigNum *bn,
  338. struct PubKey const *pub)
  339. {
  340. byte tmp[1];
  341. unsigned bytes;
  342. bndPrintf(("RSA signature checking.\n"));
  343. if (bnExpMod(bn, bn, &pub->e, &pub->n) < 0)
  344. return RSAGLUE_NOMEM;
  345. bndPut("decrypted = ", bn);
  346. bytes = (bnBits(&pub->n)+7)/8;
  347. bnExtractBigBytes(bn, tmp, bytes-2, 2);
  348. if (tmp[0] != 0 || tmp[1] != signedType) {
  349. memset(tmp, 0, 2);
  350. return RSAGLUE_CORRUPT;
  351. }
  352. bytes = bnSearchNonOneFromHigh(bn, bytes-2);
  353. if (bytes < 1)
  354. return RSAGLUE_CORRUPT;
  355. bytes--;
  356. bnExtractBigBytes(bn, tmp, bytes, 1);
  357. if (tmp[0] != 0) {
  358. tmp[0] = 0;
  359. return RSAGLUE_CORRUPT;
  360. }
  361. /* Note: tmp isn't sensitive any more because its a constant! */
  362. /* Success! Return the data */
  363. if (len > bytes)
  364. len = bytes;
  365. bnExtractBigBytes(bn, buf, bytes-len, len);
  366. return bytes;
  367. }
  368. /*
  369. * Searches bytes, beginning with start-1 and progressing to 0,
  370. * until finding one that is zero, or the end of the array.
  371. * The index of the last non-zero byte is returned (0 if the array
  372. * is all non-zero, or start if start-1 is zero).
  373. */
  374. static unsigned
  375. bnSearchZeroFromHigh(struct BigNum const *bn, unsigned start)
  376. {
  377. byte buf[16]; /* Size is arbitrary */
  378. unsigned l;
  379. unsigned i;
  380. while (start) {
  381. l = start < sizeof(buf) ? start : sizeof(buf);
  382. start -= l;
  383. bnExtractBigBytes(bn, buf, start, l);
  384. for (i = 0; i < l; i++) {
  385. if (buf[i] == 0) {
  386. memset(buf, 0, sizeof(buf));
  387. return start + l - i;
  388. }
  389. }
  390. }
  391. /* Nothing found */
  392. memset(buf, 0, sizeof(buf));
  393. return 0;
  394. }
  395. /*
  396. * Performs an RSA decryption. Returns a prefix of the unwrapped
  397. * data in the given buf. Returns the length of the untruncated
  398. * data, which may exceed "len". Returns <0 on error.
  399. */
  400. int
  401. rsaPrivateDecrypt(byte *buf, unsigned len, struct BigNum *bn,
  402. struct PubKey const *pub, struct SecKey const *sec)
  403. {
  404. unsigned bytes;
  405. byte tmp[2];
  406. bndPrintf(("RSA decrypting\n"));
  407. if (bnExpModCRA(bn, &sec->d, &sec->p, &sec->q, &sec->u) < 0)
  408. return RSAGLUE_NOMEM;
  409. bndPut("decrypted = ", bn);
  410. bytes = (bnBits(&pub->n)+7)/8;
  411. bnExtractBigBytes(bn, tmp, bytes-2, 2);
  412. if (tmp[0] != 0 || tmp[1] != 2) {
  413. memset(tmp, 0, 2);
  414. return RSAGLUE_CORRUPT;
  415. }
  416. bytes = bnSearchZeroFromHigh(bn, bytes-2);
  417. if (bytes-- == 0)
  418. return RSAGLUE_CORRUPT;
  419. if (len > bytes)
  420. len = bytes;
  421. bnExtractBigBytes(bn, buf, bytes-len, len);
  422. return bytes;
  423. }