1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner.
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works.
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h"
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** @file pkcs_1_v1_5_decode.c
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  PKCS #1 v1.5 Padding. (Andreas Lange)
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef PKCS_1
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** @brief PKCS #1 v1.5 decode.
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  @param msg              The encoded data to decode
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  @param msglen           The length of the encoded data (octets)
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  @param block_type       Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  @param modulus_bitlen   The bit length of the RSA modulus
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  @param out              [out] Destination of decoding
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  @param outlen           [in/out] The max size and resulting size of the decoding
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  @param is_valid         [out] Boolean whether the padding was valid
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *  @return CRYPT_OK if successful (even if invalid)
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint pkcs_1_v1_5_decode(const unsigned char *msg,
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                             unsigned long  msglen,
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                                       int  block_type,
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                             unsigned long  modulus_bitlen,
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                             unsigned char *out,
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                             unsigned long *outlen,
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                                       int *is_valid)
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  unsigned long modulus_len, ps_len, i;
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  int result;
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* default to invalid packet */
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  *is_valid = 0;
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* test message size */
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if ((msglen > modulus_len) || (modulus_len < 11)) {
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_PK_INVALID_SIZE;
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* separate encoded message */
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    result = CRYPT_INVALID_PACKET;
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    goto bail;
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if (block_type == LTC_PKCS_1_EME) {
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 2; i < modulus_len; i++) {
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* separator */
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if (msg[i] == 0x00) { break; }
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ps_len = i++ - 2;
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if ((i >= modulus_len) || (ps_len < 8)) {
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* There was no octet with hexadecimal value 0x00 to separate ps from m,
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       * or the length of ps is less than 8 octets.
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       */
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      result = CRYPT_INVALID_PACKET;
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      goto bail;
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  } else {
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 2; i < modulus_len - 1; i++) {
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if (msg[i] != 0xFF) { break; }
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* separator check */
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (msg[i] != 0) {
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* There was no octet with hexadecimal value 0x00 to separate ps from m. */
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      result = CRYPT_INVALID_PACKET;
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      goto bail;
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ps_len = i - 2;
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if (*outlen < (msglen - (2 + ps_len + 1))) {
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    *outlen = msglen - (2 + ps_len + 1);
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    result = CRYPT_BUFFER_OVERFLOW;
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    goto bail;
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  *outlen = (msglen - (2 + ps_len + 1));
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* valid packet */
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  *is_valid = 1;
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  result    = CRYPT_OK;
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectbail:
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  return result;
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} /* pkcs_1_v1_5_decode */
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* #ifdef PKCS_1 */
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c,v $ */
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.5 $ */
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/12/16 17:41:21 $ */
111