Ejemplo n.º 1
0
bool ClientPuzzleManager::checkOneSolution(U32 solution, Nonce &clientNonce, Nonce &serverNonce, U32 puzzleDifficulty, U32 clientIdentity)
{
   U8 buffer[8];
   writeU32ToBuffer(solution, buffer);
   writeU32ToBuffer(clientIdentity, buffer + 4);

   hash_state hashState;
   U8 hash[32];

   sha256_init(&hashState);
   sha256_process(&hashState, buffer, sizeof(buffer));
   sha256_process(&hashState, clientNonce.data, Nonce::NonceSize);
   sha256_process(&hashState, serverNonce.data, Nonce::NonceSize);
   sha256_done(&hashState, hash);

   U32 index = 0;
   while(puzzleDifficulty > 8)
   {
      if(hash[index])
         return false;
      index++;
      puzzleDifficulty -= 8;
   }
   U8 mask = 0xFF << (8 - puzzleDifficulty);
   return (mask & hash[index]) == 0;
}
Ejemplo n.º 2
0
U32 NetInterface::computeClientIdentityToken(const Address &address, const Nonce &theNonce)
{
   hash_state hashState;
   U32 hash[8];

   sha256_init(&hashState);
   sha256_process(&hashState, (const U8 *) &address, sizeof(Address));
   sha256_process(&hashState, theNonce.data, Nonce::NonceSize);
   sha256_process(&hashState, mRandomHashData, sizeof(mRandomHashData));
   sha256_done(&hashState, (U8 *) hash);

   return hash[0];
}
Ejemplo n.º 3
0
/**
 * sha256_vector - SHA256 hash for data vector
 * @num_elem: Number of elements in the data vector
 * @addr: Pointers to the data areas
 * @len: Lengths of the data blocks
 * @mac: Buffer for the hash
 * @pScratchMem: Scratch memory; At least (108 + 288) = 396 bytes.
 */
void
sha256_vector(void *priv, size_t num_elem,
	      UINT8 *addr[], size_t * len, UINT8 *mac, UINT8 *pScratchMem)
{
	UINT8 *pTmpBuf;
	size_t i;
	struct sha256_state *pCtx;

	/*
	 ** sizeof(struct sha256_state)
	 **
	 **    UINT64 length                      =  8
	 **    UINT32 state[8], curlen; = (9 * 4) = 36
	 **    UINT8 buf[64];                     = 64
	 **                                       -----
	 **                                        108
	 */
	pCtx = (struct sha256_state *)pScratchMem;
	pTmpBuf = pScratchMem + sizeof(struct sha256_state);

	sha256_init(pCtx);

	for (i = 0; i < num_elem; i++) {
		/* pTmpBuf = At least 288 bytes of memory */
		sha256_process((void *)priv, pCtx, addr[i], len[i], pTmpBuf);
	}
	sha256_done((void *)priv, pCtx, mac, pTmpBuf);
}
Ejemplo n.º 4
0
static int _sha256(unsigned char *hash, const unsigned char *data, const int datalen) {
   hash_state md;
   sha256_init(&md);
   sha256_process(&md, data, datalen);
   sha256_done(&md, hash);
   return CRYPT_OK;
}
Ejemplo n.º 5
0
void sha256(unsigned char* in, size_t in_size, unsigned char* out)
{
    hash_state h;
    sha256_init(&h);
    sha256_process(&h, in, (unsigned long)in_size);
    sha256_done(&h, out);
}
Ejemplo n.º 6
0
void sha256_buffer(const unsigned char *buffer, size_t len,
                  unsigned char hash[32])
{
    sha256_state md;

    sha256_init(&md);
    sha256_process(&md, buffer, len);
    sha256_done(&md, hash);
}
Ejemplo n.º 7
0
void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
                 size_t DataLength,byte *ResDigest)
{
  const size_t Sha256BlockSize=64; // As defined in RFC 4868.

  byte KeyHash[SHA256_DIGEST_SIZE];
  if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash.
  {
    sha256_context KCtx;
    sha256_init(&KCtx);
    sha256_process(&KCtx, Key, KeyLength);
    sha256_done(&KCtx, KeyHash);

    Key = KeyHash;
    KeyLength = SHA256_DIGEST_SIZE;
  }

  byte KeyBuf[Sha256BlockSize]; // Store the padded key here.
  for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest.
    KeyBuf[I] = Key[I] ^ 0x36;
  for (size_t I = KeyLength; I < Sha256BlockSize; I++)
    KeyBuf[I] = 0x36;

  sha256_context ICtx;
  sha256_init(&ICtx);
  sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key.
  sha256_process(&ICtx, Data, DataLength); // Hash data.

  byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data.
  sha256_done(&ICtx, IDig);

  sha256_context RCtx;
  sha256_init(&RCtx);

  for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding.
    KeyBuf[I] = Key[I] ^ 0x5c;
  for (size_t I = KeyLength; I < Sha256BlockSize; I++)
    KeyBuf[I] = 0x5c;

  sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key.
  sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest.

  sha256_done(&RCtx, ResDigest);
}
Ejemplo n.º 8
0
int HashSHA256 (uint8 *value, int len, uint8* hashcode)
{
    sha256_state sha256State;

    sha256_init(&sha256State);
    sha256_process(&sha256State, value, len);
    sha256_done(&sha256State, hashcode);

    return 0;
}
Ejemplo n.º 9
0
/**
 * sha256_vector - SHA256 hash for data vector
 * @num_elem: Number of elements in the data vector
 * @addr: Pointers to the data areas
 * @len: Lengths of the data blocks
 * @mac: Buffer for the hash
 */
void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
		 u8 *mac)
{
	struct sha256_state ctx;
	size_t i;

	sha256_init(&ctx);
	for (i = 0; i < num_elem; i++)
		sha256_process(&ctx, addr[i], len[i]);
	sha256_done(&ctx, mac);
}
Ejemplo n.º 10
0
/**
 * SHA256 Hashing
 * @addr: pointers to the data area
 * @len: Lengths of the data block
 * @res: Buffer for the digest
 * Returns: 0 on success, -1 of failure
 */
int sha256(const unsigned char *addr, const size_t len,
		   unsigned char *res)
{
	struct sha256_state ctx;

	sha256_init(&ctx);

	if (sha256_process(&ctx, addr, len) || sha256_done(&ctx, res))
		return -1;

	return 0;
}
Ejemplo n.º 11
0
void sha256_update (sha256_context *cur, U8 *data, U32 len)
{
    // If our current length is bigger than a block, just keep on 
    // processing it until it isn't.
    while (len >= SHA_256_BLOCKSIZE)
    {
 	sha256_process(cur, data);
	cur->bits += SHA_256_BLOCKSIZEBITS;
	data += SHA_256_BLOCKSIZE;
        len -= SHA_256_BLOCKSIZE;
    }
	
    // So we need to deal with whatever is leftover. We know the current
    // buffer location, and we want to store the smaller of the leftover
    // length or the rest of the buffer. Find that value and then store
    // the leftovers.
    if (len > 0)
    {
 	U32 avail_space = len < SHA_256_BLOCKSIZE - cur->holdlength ?
		len : SHA_256_BLOCKSIZE - cur->holdlength;

	memcpy(&cur->buffer[cur->holdlength], data, avail_space);
	cur->holdlength += avail_space;
	data += avail_space;
	len -= avail_space;
	
	// If that just left our buffer with a full block, process it.
	if (cur->holdlength == SHA_256_BLOCKSIZE)
	{
		sha256_process(cur, cur->buffer);
		cur->bits += SHA_256_BLOCKSIZEBITS;
		cur->holdlength = 0;
	}	
    }
	
    // Right now holdlength holds the leftover bytes that we need to process,
    // so be sure to increment our bit count.
    cur->bits += cur->holdlength * 8;
}
Ejemplo n.º 12
0
/**
 * sha256_vector - SHA256 hash for data vector
 * @num_elem: Number of elements in the data vector
 * @addr: Pointers to the data areas
 * @len: Lengths of the data blocks
 * @mac: Buffer for the hash
 * Returns: 0 on success, -1 of failure
 */
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
		  u8 *mac)
{
	struct sha256_state ctx;
	size_t i;

	sha256_init(&ctx);
	for (i = 0; i < num_elem; i++)
		if (sha256_process(&ctx, addr[i], len[i]))
			return -1;
	if (sha256_done(&ctx, mac))
		return -1;
	return 0;
}
Ejemplo n.º 13
0
void sha256_finish (sha256_context *cur, U8 *res )
{
    // We need to pad the start of our data with a 1 and the end of our
    // data with a bunch of zeroes
    cur->buffer[cur->holdlength++] = 0x80;

    // If our buffer holds more than 56 bytes (64-8) we are going to 
    // pad it with zeros and shove it off for compression.
    if (cur->holdlength > SHA_256_BLOCKSIZE - 8)
    {
	memset(&cur->buffer[cur->holdlength++], (U8)0, (SHA_256_BLOCKSIZE - cur->holdlength));
	sha256_process(cur, cur->buffer);
	cur->holdlength = 0;
    }
	
    // Prepare for the final compression step. Pad zeros until we have just
    // enough room to pad the number of bits onto the end.
    memset(&cur->buffer[cur->holdlength++], (U8)0, (56 - cur->holdlength));

    // Pad our data with the length, fire off a transformation and we are
    // done!
    //TODO: Fix this, this is not as easy as it should be. 
    U32 length_high = cur->bits >> 32;
    U32 length_low = cur->bits & 0xffffffff;
								
    U32_TO_U8(length_high, cur->buffer, 56);
    U32_TO_U8(length_low, cur->buffer, 60);

    sha256_process(cur, cur->buffer);
	
    // Transfer our result (in cur->state) to our result pointer.
    U8 i;
    for (i = 0; i <8; i++)
    {
    	U32_TO_U8 (cur->state[i], res, i*4);
    }
}
Ejemplo n.º 14
0
Archivo: sha2.cpp Proyecto: DINKIN/omim
 string digest256(char const * data, size_t dataSize, bool returnAsHexString)
 {
   hash_state md;
   unsigned char out[256/8] = { 0 };
   if (CRYPT_OK == sha256_init(&md)
       && CRYPT_OK == sha256_process(&md, reinterpret_cast<unsigned char const *>(data), dataSize)
       && CRYPT_OK == sha256_done(&md, out))
   {
     if (returnAsHexString)
       return ToHex(string(reinterpret_cast<char const *>(out), ARRAY_SIZE(out)));
     else
       return string(reinterpret_cast<char const *>(out), ARRAY_SIZE(out));
   }
   return string();
 }
Ejemplo n.º 15
0
int
yacl_sha256_file (FILE *fp, uint8_t *out)
{
  struct sha256_state state;
  sha256_init(&state);

  int c;
  int rc = -1;
  /* Perform the hash */
  while ((c = getc (fp)) != EOF)
    {
      rc = sha256_process (&state, &c, sizeof c);
      if (rc) goto OUT;
    }

  sha256_done (&state, out);

  rc = 0;
 OUT:
  return rc;

}
Ejemplo n.º 16
0
/*---------------------------------------------------------------------------*/
static void
at_cmd_sha256_callback(struct at_cmd *cmd, uint8_t len, char *data)
{
  /* Format: AT&SHA256=s, where s is a string up to 64 bytes */
  uint8_t i;
  char tmp[4], sha256[32], sha256_res[64];
  static sha256_state_t state;

  crypto_init();
  if(sha256_init(&state) != CRYPTO_SUCCESS) {
    AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR);
    return;
  }

  if(sha256_process(&state, &data[10],
                    len - (cmd->cmd_hdr_len)) != CRYPTO_SUCCESS) {
    AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR);
    return;
  }

  if(sha256_done(&state, sha256) != CRYPTO_SUCCESS) {
    AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR);
    return;
  }

  crypto_disable();

  PRINTF("Input: %s:\n", &data[10]);
  snprintf(tmp, 3, "%02X", sha256[0]);
  strncpy(sha256_res, tmp, 3);
  for(i = 1; i < 32; i++) {
    PRINTF("0x%02X ", sha256[i]);
    snprintf(tmp, 3, "%02X", sha256[i]);
    strcat(sha256_res, tmp);
  }
  PRINTF("\nSHA256: %s\n", sha256_res);
  AT_RESPONSE(sha256_res);
  AT_RESPONSE(AT_DEFAULT_RESPONSE_OK);
}
Ejemplo n.º 17
0
/**
  Self-test the hash
  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
*/  
int  sha256_test(void)
{
 #ifndef LTC_TEST
    return CRYPT_NOP;
 #else    
  static const struct {
      char *msg;
      unsigned char hash[32];
  } tests[] = {
    { "abc",
      { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
        0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
        0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
        0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
    },
    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
      { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 
        0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
        0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 
        0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
    },
  };

  int i;
  unsigned char tmp[32];
  hash_state md;

  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
      sha256_init(&md);
      sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
      sha256_done(&md, tmp);
      if (memcmp(tmp, tests[i].hash, 32) != 0) {
         return CRYPT_FAIL_TESTVECTOR;
      }
  }
  return CRYPT_OK;
 #endif
}
Ejemplo n.º 18
0
static void sha256_process_wrap( void *ctx, const unsigned char *data )
{
    sha256_process( (sha256_context *) ctx, data );
}
Ejemplo n.º 19
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(sha256_test_process, ev, data)
{
  static const char *const str_res[] = {
    "success",
    "invalid param",
    "NULL error",
    "resource in use",
    "DMA bus error"
  };
  static const struct {
    const char *data[3];
    uint8_t sha256[32];
  } vectors[] = {
    { /* Simple */
      {
        "abc",
        NULL,
        NULL
      }, {
        0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
        0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
        0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
        0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
      }
    }, { /* Simple */
      {
        "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
        NULL,
        NULL,
      }, {
        0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
        0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
        0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
        0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
      }
    }, { /* Message of length 130 */
      {
        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklabcd"
        "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn",
        NULL,
        NULL
      }, {
        0x15, 0xd2, 0x3e, 0xea, 0x57, 0xb3, 0xd4, 0x61,
        0xbf, 0x38, 0x91, 0x12, 0xab, 0x4c, 0x43, 0xce,
        0x85, 0xe1, 0x68, 0x23, 0x8a, 0xaa, 0x54, 0x8e,
        0xc8, 0x6f, 0x0c, 0x9d, 0x65, 0xf9, 0xb9, 0x23
      }
    }, { /* Message of length 128 */
      {
        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklabcd"
        "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl",
        NULL,
        NULL
      }, {
        0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9,
        0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66,
        0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78,
        0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f
      }
    }, { /* Message of length 64 */
      {
        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl",
        NULL,
        NULL
      }, {
        0x2f, 0xcd, 0x5a, 0x0d, 0x60, 0xe4, 0xc9, 0x41,
        0x38, 0x1f, 0xcc, 0x4e, 0x00, 0xa4, 0xbf, 0x8b,
        0xe4, 0x22, 0xc3, 0xdd, 0xfa, 0xfb, 0x93, 0xc8,
        0x09, 0xe8, 0xd1, 0xe2, 0xbf, 0xff, 0xae, 0x8e
      }
    }, { /* Message of length 66 */
      {
        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn",
        NULL,
        NULL
      }, {
        0x92, 0x90, 0x1c, 0x85, 0x82, 0xe3, 0x1c, 0x05,
        0x69, 0xb5, 0x36, 0x26, 0x9c, 0xe2, 0x2c, 0xc8,
        0x30, 0x8b, 0xa4, 0x17, 0xab, 0x36, 0xc1, 0xbb,
        0xaf, 0x08, 0x4f, 0xf5, 0x8b, 0x18, 0xdc, 0x6a
      }
    }, {
      {
        "abcdbcdecdefde",
        "fgefghfghighijhijkijkljklmklmnlmnomnopnopq",
        NULL
      }, {
        0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
        0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
        0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
        0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
      }
    }, {
      {
        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl",
        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl",
        NULL
      }, {
        0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9,
        0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66,
        0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78,
        0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f
      }
    }, {
      {
        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh",
        "ijkl",
        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl"
      }, {
        0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9,
        0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66,
        0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78,
        0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f
      }
    }
  };
  static sha256_state_t state;
  static uint8_t sha256[32];
  static int i, j;
  static uint8_t ret;
  static rtimer_clock_t total_time;
  rtimer_clock_t time;
  size_t len;

  PROCESS_BEGIN();

  puts("-----------------------------------------\n"
       "Initializing cryptoprocessor...");
  crypto_init();

  for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) {
    printf("-----------------------------------------\n"
           "Test vector #%d:\n", i);

    time = RTIMER_NOW();
    ret = sha256_init(&state);
    time = RTIMER_NOW() - time;
    total_time = time;
    printf("sha256_init(): %s, %lu us\n", str_res[ret],
           (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
    PROCESS_PAUSE();
    if(ret != CRYPTO_SUCCESS) {
      continue;
    }

    for(j = 0; j < sizeof(vectors[i].data) / sizeof(vectors[i].data[0]) &&
               vectors[i].data[j] != NULL; j++) {
      len = strlen(vectors[i].data[j]);
      printf("Buffer #%d (length: %u):\n", j, len);
      time = RTIMER_NOW();
      ret = sha256_process(&state, vectors[i].data[j], len);
      time = RTIMER_NOW() - time;
      total_time += time;
      printf("sha256_process(): %s, %lu us\n", str_res[ret],
             (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
      PROCESS_PAUSE();
      if(ret != CRYPTO_SUCCESS) {
        break;
      }
    }
    if(ret != CRYPTO_SUCCESS) {
      continue;
    }

    time = RTIMER_NOW();
    ret = sha256_done(&state, sha256);
    time = RTIMER_NOW() - time;
    total_time += time;
    printf("sha256_done(): %s, %lu us\n", str_res[ret],
           (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
    PROCESS_PAUSE();
    if(ret != CRYPTO_SUCCESS) {
      continue;
    }

    if(rom_util_memcmp(sha256, vectors[i].sha256, sizeof(sha256))) {
      puts("Computed SHA-256 hash does not match expected hash");
    } else {
      puts("Computed SHA-256 hash OK");
    }
    printf("Total duration: %lu us\n",
           (uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND));
  }

  puts("-----------------------------------------\n"
       "Disabling cryptoprocessor...");
  crypto_disable();

  puts("Done!");

  PROCESS_END();
}
Ejemplo n.º 20
0
static void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
                        size_t DataLength,byte *ResDigest,
                        sha256_context *ICtxOpt,bool *SetIOpt,
                        sha256_context *RCtxOpt,bool *SetROpt)
{
  const size_t Sha256BlockSize=64; // As defined in RFC 4868.

  byte KeyHash[SHA256_DIGEST_SIZE];
  if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash.
  {
    sha256_context KCtx;
    sha256_init(&KCtx);
    sha256_process(&KCtx, Key, KeyLength);
    sha256_done(&KCtx, KeyHash);

    Key = KeyHash;
    KeyLength = SHA256_DIGEST_SIZE;
  }

  byte KeyBuf[Sha256BlockSize]; // Store the padded key here.
  sha256_context ICtx;

  if (ICtxOpt!=NULL && *SetIOpt)
    ICtx=*ICtxOpt; // Use already calculated first block context.
  else
  {
    // This calculation is the same for all iterations with same password.
    // So for PBKDF2 we can calculate it only for first block and then reuse
    // to improve performance. 

    for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest.
      KeyBuf[I] = Key[I] ^ 0x36;
    for (size_t I = KeyLength; I < Sha256BlockSize; I++)
      KeyBuf[I] = 0x36;

    sha256_init(&ICtx);
    sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key.
  }

  if (ICtxOpt!=NULL && !*SetIOpt) // Store constant context for further reuse.
  {
    *ICtxOpt=ICtx;
    *SetIOpt=true;
  }

  sha256_process(&ICtx, Data, DataLength); // Hash data.

  byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data.
  sha256_done(&ICtx, IDig);

  sha256_context RCtx;

  if (RCtxOpt!=NULL && *SetROpt)
    RCtx=*RCtxOpt; // Use already calculated first block context.
  else
  {
    // This calculation is the same for all iterations with same password.
    // So for PBKDF2 we can calculate it only for first block and then reuse
    // to improve performance. 

    for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding.
      KeyBuf[I] = Key[I] ^ 0x5c;
    for (size_t I = KeyLength; I < Sha256BlockSize; I++)
      KeyBuf[I] = 0x5c;

    sha256_init(&RCtx);
    sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key.
  }

  if (RCtxOpt!=NULL && !*SetROpt) // Store constant context for further reuse.
  {
    *RCtxOpt=RCtx;
    *SetROpt=true;
  }

  sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest.

  sha256_done(&RCtx, ResDigest);
}
Ejemplo n.º 21
0
/**
 * u2fs_registration_verify:
 * @ctx: a context handle, from u2fs_init().
 * @response: a U2F registration response message Base64 encoded.
 * @output: pointer to output structure containing the relevant data for a well formed request. Memory should be free'd.
 *
 * Get a U2F registration response and check its validity.
 *
 * Returns: On success %U2FS_OK (integer 0) is returned and @output is filled up with the user public key, the key handle and the attestation certificate. On errors
 * a #u2fs_rc error code.
 */
u2fs_rc u2fs_registration_verify(u2fs_ctx_t * ctx, const char *response,
                                 u2fs_reg_res_t ** output)
{
  char *registrationData;
  char *clientData;
  char *clientData_decoded;
  unsigned char *user_public_key;
  size_t keyHandle_len;
  char *keyHandle;
  char *origin;
  char *challenge;
  char buf[_B64_BUFSIZE];
  unsigned char c = 0;
  u2fs_X509_t *attestation_certificate;
  u2fs_ECDSA_t *signature;
  u2fs_EC_KEY_t *key;
  u2fs_rc rc;

  if (ctx == NULL || response == NULL || output == NULL)
    return U2FS_MEMORY_ERROR;

  key = NULL;
  clientData_decoded = NULL;
  challenge = NULL;
  origin = NULL;
  attestation_certificate = NULL;
  user_public_key = NULL;
  signature = NULL;
  registrationData = NULL;
  clientData = NULL;
  keyHandle = NULL;
  *output = NULL;

  rc = parse_registration_response(response, &registrationData,
                                   &clientData);
  if (rc != U2FS_OK)
    goto failure;

  if (debug) {
    fprintf(stderr, "registrationData: %s\n", registrationData);
    fprintf(stderr, "clientData: %s\n", clientData);
  }

  rc = parse_registrationData(registrationData, &user_public_key,
                              &keyHandle_len, &keyHandle,
                              &attestation_certificate, &signature);
  if (rc != U2FS_OK)
    goto failure;

  rc = extract_EC_KEY_from_X509(attestation_certificate, &key);

  if (rc != U2FS_OK)
    goto failure;

  //TODO Add certificate validation

  rc = decode_clientData(clientData, &clientData_decoded);

  if (rc != U2FS_OK)
    goto failure;

  rc = parse_clientData(clientData_decoded, &challenge, &origin);

  if (rc != U2FS_OK)
    goto failure;

  if (strcmp(ctx->challenge, challenge) != 0) {
    rc = U2FS_CHALLENGE_ERROR;
    goto failure;
  }

  if (strcmp(ctx->origin, origin) != 0) {
    rc = U2FS_ORIGIN_ERROR;
    goto failure;
  }

  struct sha256_state sha_ctx;
  char challenge_parameter[U2FS_HASH_LEN],
      application_parameter[U2FS_HASH_LEN];

  sha256_init(&sha_ctx);
  sha256_process(&sha_ctx, (unsigned char *) ctx->appid,
                 strlen(ctx->appid));
  sha256_done(&sha_ctx, (unsigned char *) application_parameter);

  sha256_init(&sha_ctx);
  sha256_process(&sha_ctx, (unsigned char *) clientData_decoded,
                 strlen(clientData_decoded));
  sha256_done(&sha_ctx, (unsigned char *) challenge_parameter);

  unsigned char dgst[U2FS_HASH_LEN];
  sha256_init(&sha_ctx);
  sha256_process(&sha_ctx, &c, 1);
  sha256_process(&sha_ctx, (unsigned char *) application_parameter,
                 U2FS_HASH_LEN);
  sha256_process(&sha_ctx, (unsigned char *) challenge_parameter,
                 U2FS_HASH_LEN);
  sha256_process(&sha_ctx, (unsigned char *) keyHandle, keyHandle_len);
  sha256_process(&sha_ctx, user_public_key, U2FS_PUBLIC_KEY_LEN);
  sha256_done(&sha_ctx, dgst);

  rc = verify_ECDSA(dgst, U2FS_HASH_LEN, signature, key);

  if (rc != U2FS_OK)
    goto failure;

  free_sig(signature);
  signature = NULL;

  *output = calloc(1, sizeof(**output));
  if (*output == NULL) {
    rc = U2FS_MEMORY_ERROR;
    goto failure;
  }

  rc = encode_b64u(keyHandle, keyHandle_len, buf);
  if (rc != U2FS_OK)
    goto failure;

  u2fs_EC_KEY_t *key_ptr;
  (*output)->keyHandle = strndup(buf, strlen(buf));

  rc = decode_user_key(user_public_key, &key_ptr);
  if (rc != U2FS_OK)
    goto failure;

  (*output)->attestation_certificate = dup_cert(attestation_certificate);

  rc = dump_user_key(key_ptr, &(*output)->publicKey);
  if (rc != U2FS_OK)
    goto failure;

  rc = dump_X509_cert(attestation_certificate, &(*output)->attestation_certificate_PEM);
  if (rc != U2FS_OK)
    goto failure;

  if ((*output)->keyHandle == NULL
      || (*output)->publicKey == NULL
      || (*output)->attestation_certificate == NULL) {
    rc = U2FS_MEMORY_ERROR;
    goto failure;
  }

  free_key(key);
  key = NULL;

  free_cert(attestation_certificate);
  attestation_certificate = NULL;

  free(clientData_decoded);
  clientData_decoded = NULL;

  free(challenge);
  challenge = NULL;

  free(origin);
  origin = NULL;

  free(user_public_key);
  user_public_key = NULL;

  free(registrationData);
  registrationData = NULL;

  free(clientData);
  clientData = NULL;

  free(keyHandle);
  keyHandle = NULL;

  return U2FS_OK;

failure:
  if (key) {
    free_key(key);
    key = NULL;
  }

  if (clientData_decoded) {
    free(clientData_decoded);
    clientData_decoded = NULL;
  }

  if (challenge) {
    free(challenge);
    challenge = NULL;
  }

  if (origin) {
    free(origin);
    origin = NULL;
  }

  if (attestation_certificate) {
    free_cert(attestation_certificate);
    attestation_certificate = NULL;
  }

  if (user_public_key) {
    free(user_public_key);
    user_public_key = NULL;
  }

  if (signature) {
    free_sig(signature);
    signature = NULL;
  }

  if (registrationData) {
    free(registrationData);
    registrationData = NULL;
  }

  if (clientData) {
    free(clientData);
    clientData = NULL;
  }

  if (keyHandle) {
    free(keyHandle);
    keyHandle = NULL;
  }

  return rc;
}
Ejemplo n.º 22
0
/**
 * u2fs_authentication_verify:
 * @ctx: a context handle, from u2fs_init()
 * @response: pointer to output string with JSON data.
 * @output: pointer to output structure containing the relevant data for a well formed request. Memory should be free'd.
 *
 * Get a U2F authentication response and check its validity.
 *
 * Returns: On a successful verification %U2FS_OK (integer 0) is returned and @output is filled with the authentication result (same as the returned value), the counter received from the token and the user presence information. On errors
 * a #u2fs_rc error code is returned.
 */
u2fs_rc u2fs_authentication_verify(u2fs_ctx_t * ctx, const char *response,
                                   u2fs_auth_res_t ** output)
{
  char *signatureData;
  char *clientData;
  char *clientData_decoded;
  char *keyHandle;
  char *challenge;
  char *origin;
  uint8_t user_presence;
  uint32_t counter_num;
  uint32_t counter;
  u2fs_ECDSA_t *signature;
  u2fs_rc rc;

  if (ctx == NULL || response == NULL || output == NULL)
    return U2FS_MEMORY_ERROR;

  signatureData = NULL;
  clientData = NULL;
  clientData_decoded = NULL;
  keyHandle = NULL;
  challenge = NULL;
  origin = NULL;
  signature = NULL;
  *output = NULL;

  rc = parse_authentication_response(response, &signatureData,
                                     &clientData, &keyHandle);
  if (rc != U2FS_OK)
    goto failure;

  if (debug) {
    fprintf(stderr, "signatureData: %s\n", signatureData);
    fprintf(stderr, "clientData: %s\n", clientData);
    fprintf(stderr, "keyHandle: %s\n", keyHandle);
  }

  rc = parse_signatureData(signatureData, &user_presence,
                           &counter, &signature);
  if (rc != U2FS_OK)
    goto failure;

  rc = decode_clientData(clientData, &clientData_decoded);

  if (rc != U2FS_OK)
    goto failure;

  rc = parse_clientData(clientData_decoded, &challenge, &origin);

  if (rc != U2FS_OK)
    goto failure;

  if (strcmp(ctx->challenge, challenge) != 0) {
    rc = U2FS_CHALLENGE_ERROR;
    goto failure;
  }

  if (strcmp(ctx->origin, origin) != 0) {
    rc = U2FS_ORIGIN_ERROR;
    goto failure;
  }

  struct sha256_state sha_ctx;
  char challenge_parameter[U2FS_HASH_LEN],
      application_parameter[U2FS_HASH_LEN];

  sha256_init(&sha_ctx);
  sha256_process(&sha_ctx, (unsigned char *) ctx->appid,
                 strlen(ctx->appid));
  sha256_done(&sha_ctx, (unsigned char *) application_parameter);

  sha256_init(&sha_ctx);
  sha256_process(&sha_ctx, (unsigned char *) clientData_decoded,
                 strlen(clientData_decoded));
  sha256_done(&sha_ctx, (unsigned char *) challenge_parameter);

  unsigned char dgst[U2FS_HASH_LEN];
  sha256_init(&sha_ctx);
  sha256_process(&sha_ctx, (unsigned char *) application_parameter,
                 U2FS_HASH_LEN);
  sha256_process(&sha_ctx, (unsigned char *) &user_presence, 1);
  sha256_process(&sha_ctx, (unsigned char *) &counter, U2FS_COUNTER_LEN);
  sha256_process(&sha_ctx, (unsigned char *) challenge_parameter,
                 U2FS_HASH_LEN);
  sha256_done(&sha_ctx, dgst);

  rc = verify_ECDSA(dgst, U2FS_HASH_LEN, signature, ctx->key);

  if (rc != U2FS_OK)
    goto failure;

  free_sig(signature);
  signature = NULL;

  *output = calloc(1, sizeof(**output));
  if (*output == NULL) {
    rc = U2FS_MEMORY_ERROR;
    goto failure;
  }

  counter_num = 0;
  counter_num |= (counter & 0xFF000000) >> 24;
  counter_num |= (counter & 0x00FF0000) >> 8;
  counter_num |= (counter & 0x0000FF00) << 8;
  counter_num |= (counter & 0x000000FF) << 24;

  (*output)->verified = U2FS_OK;
  (*output)->user_presence = user_presence;
  (*output)->counter = counter_num;

  free(origin);
  origin = NULL;

  free(challenge);
  challenge = NULL;

  free(keyHandle);
  keyHandle = NULL;

  free(signatureData);
  signatureData = NULL;

  free(clientData);
  clientData = NULL;

  free(clientData_decoded);
  clientData_decoded = NULL;

  return U2FS_OK;

failure:
  if (clientData_decoded) {
    free(clientData_decoded);
    clientData_decoded = NULL;
  }

  if (challenge) {
    free(challenge);
    challenge = NULL;
  }

  if (origin) {
    free(origin);
    origin = NULL;
  }

  if (signature) {
    free_sig(signature);
    signature = NULL;
  }

  if (signatureData) {
    free(signatureData);
    signatureData = NULL;
  }

  if (clientData) {
    free(clientData);
    clientData = NULL;
  }

  if (keyHandle) {
    free(keyHandle);
    keyHandle = NULL;
  }

  return rc;
}