/contrib/pgcrypto/pgp-pubenc.c

https://github.com/guocongwudi/9315ass2 · C · 250 lines · 163 code · 33 blank · 54 comment · 27 complexity · 90c4b8eb3dc4c3a7502288dcc9cb87ff MD5 · raw file

  1. /*
  2. * pgp-pubenc.c
  3. * Encrypt session key with public key.
  4. *
  5. * Copyright (c) 2005 Marko Kreen
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. *
  29. * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubenc.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
  30. */
  31. #include "postgres.h"
  32. #include "px.h"
  33. #include "mbuf.h"
  34. #include "pgp.h"
  35. /*
  36. * padded msg: 02 || non-zero pad bytes || 00 || msg
  37. */
  38. static int
  39. pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
  40. {
  41. int res;
  42. uint8 *buf,
  43. *p;
  44. int pad_len = res_len - 2 - data_len;
  45. if (pad_len < 8)
  46. return PXE_BUG;
  47. buf = px_alloc(res_len);
  48. buf[0] = 0x02;
  49. res = px_get_random_bytes(buf + 1, pad_len);
  50. if (res < 0)
  51. {
  52. px_free(buf);
  53. return res;
  54. }
  55. /* pad must not contain zero bytes */
  56. p = buf + 1;
  57. while (p < buf + 1 + pad_len)
  58. {
  59. if (*p == 0)
  60. {
  61. res = px_get_random_bytes(p, 1);
  62. if (res < 0)
  63. break;
  64. }
  65. if (*p != 0)
  66. p++;
  67. }
  68. if (res < 0)
  69. {
  70. memset(buf, 0, res_len);
  71. px_free(buf);
  72. return res;
  73. }
  74. buf[pad_len + 1] = 0;
  75. memcpy(buf + pad_len + 2, data, data_len);
  76. *res_p = buf;
  77. return 0;
  78. }
  79. static int
  80. create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
  81. {
  82. uint8 *secmsg;
  83. int res,
  84. i;
  85. unsigned cksum = 0;
  86. int klen = ctx->sess_key_len;
  87. uint8 *padded = NULL;
  88. PGP_MPI *m = NULL;
  89. /* calc checksum */
  90. for (i = 0; i < klen; i++)
  91. cksum += ctx->sess_key[i];
  92. /*
  93. * create "secret message"
  94. */
  95. secmsg = px_alloc(klen + 3);
  96. secmsg[0] = ctx->cipher_algo;
  97. memcpy(secmsg + 1, ctx->sess_key, klen);
  98. secmsg[klen + 1] = (cksum >> 8) & 0xFF;
  99. secmsg[klen + 2] = cksum & 0xFF;
  100. /*
  101. * now create a large integer of it
  102. */
  103. res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
  104. if (res >= 0)
  105. {
  106. /* first byte will be 0x02 */
  107. int full_bits = full_bytes * 8 - 6;
  108. res = pgp_mpi_create(padded, full_bits, &m);
  109. }
  110. if (padded)
  111. {
  112. memset(padded, 0, full_bytes);
  113. px_free(padded);
  114. }
  115. memset(secmsg, 0, klen + 3);
  116. px_free(secmsg);
  117. if (res >= 0)
  118. *msg_p = m;
  119. return res;
  120. }
  121. static int
  122. encrypt_and_write_elgamal(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
  123. {
  124. int res;
  125. PGP_MPI *m = NULL,
  126. *c1 = NULL,
  127. *c2 = NULL;
  128. /* create padded msg */
  129. res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
  130. if (res < 0)
  131. goto err;
  132. /* encrypt it */
  133. res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
  134. if (res < 0)
  135. goto err;
  136. /* write out */
  137. res = pgp_mpi_write(pkt, c1);
  138. if (res < 0)
  139. goto err;
  140. res = pgp_mpi_write(pkt, c2);
  141. err:
  142. pgp_mpi_free(m);
  143. pgp_mpi_free(c1);
  144. pgp_mpi_free(c2);
  145. return res;
  146. }
  147. static int
  148. encrypt_and_write_rsa(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
  149. {
  150. int res;
  151. PGP_MPI *m = NULL,
  152. *c = NULL;
  153. /* create padded msg */
  154. res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
  155. if (res < 0)
  156. goto err;
  157. /* encrypt it */
  158. res = pgp_rsa_encrypt(pk, m, &c);
  159. if (res < 0)
  160. goto err;
  161. /* write out */
  162. res = pgp_mpi_write(pkt, c);
  163. err:
  164. pgp_mpi_free(m);
  165. pgp_mpi_free(c);
  166. return res;
  167. }
  168. int
  169. pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
  170. {
  171. int res;
  172. PGP_PubKey *pk = ctx->pub_key;
  173. uint8 ver = 3;
  174. PushFilter *pkt = NULL;
  175. uint8 algo;
  176. if (pk == NULL)
  177. {
  178. px_debug("no pubkey?\n");
  179. return PXE_BUG;
  180. }
  181. algo = pk->algo;
  182. /*
  183. * now write packet
  184. */
  185. res = pgp_create_pkt_writer(dst, PGP_PKT_PUBENCRYPTED_SESSKEY, &pkt);
  186. if (res < 0)
  187. goto err;
  188. res = pushf_write(pkt, &ver, 1);
  189. if (res < 0)
  190. goto err;
  191. res = pushf_write(pkt, pk->key_id, 8);
  192. if (res < 0)
  193. goto err;
  194. res = pushf_write(pkt, &algo, 1);
  195. if (res < 0)
  196. goto err;
  197. switch (algo)
  198. {
  199. case PGP_PUB_ELG_ENCRYPT:
  200. res = encrypt_and_write_elgamal(ctx, pk, pkt);
  201. break;
  202. case PGP_PUB_RSA_ENCRYPT:
  203. case PGP_PUB_RSA_ENCRYPT_SIGN:
  204. res = encrypt_and_write_rsa(ctx, pk, pkt);
  205. break;
  206. }
  207. if (res < 0)
  208. goto err;
  209. /*
  210. * done, signal packet end
  211. */
  212. res = pushf_flush(pkt);
  213. err:
  214. if (pkt)
  215. pushf_free(pkt);
  216. return res;
  217. }