Skip to content

Instantly share code, notes, and snippets.

@landonf
Created August 10, 2015 16:14
Show Gist options
  • Save landonf/2b36ca4c632b20df6d7e to your computer and use it in GitHub Desktop.
Save landonf/2b36ca4c632b20df6d7e to your computer and use it in GitHub Desktop.
/*
* Copyright (c) 2014 Plausible Labs Cooperative, Inc.
* All rights reserved.
*/
#import "PLCryptoConstantTime.h"
/**
* @ingroup plcrypto
* @{
*/
NSUInteger plcrypto_constant_time_compare_internal (const void *s1, size_t s1len, const void *s2, size_t s2len);
/* Function pointer indirection, used to prevent the compiler from inlining plcrypto_constant_time_compare_internal() */
NSUInteger (* volatile plcrypto_constant_time_compare_internal_ptr)(const void *s1, size_t s1len, const void *s2, size_t s2len) = plcrypto_constant_time_compare_internal;
/**
* @internal
*
* Returns 0 if @a s1 is equal to @a s2, performing the comparison in constant time as to avoid leaking
* information regarding where the values differ.
*
* @param s1 The first array to compare.
* @param s1len The length of s1.
* @param s2 The second array to compare.
* @param s2len The length of s2.
* @return 0 If the receiver is equal to @a other, otherwise a non-zero value.
*/
NSUInteger plcrypto_constant_time_compare_internal (const void *s1, size_t s1len, const void *s2, size_t s2len) {
if (s1len != s2len) {
return 1;
}
const uint8_t *aPtr = s1;
const uint8_t *bPtr = s2;
NSUInteger accumulator = 0;
for (NSUInteger i = 0; i < s1len; i++) {
accumulator |= (aPtr[i] ^ bPtr[i]);
}
/* We don't do a == 0 here, as we don't want a way-too-smart compiler to optimize the above to a memcmp */
return accumulator;
}
/**
* Returns a Boolean value that indicates whether the receiver is equal to the given instance,
* performing the comparison in constant time as to avoid leaking information regarding where
* the values differ.
*
* Note that if the two values do not have the same length, this function returns immediately.
*
* @param other The object with which to compare the receiver.
* @return YES If the receiver is equal to @a other, otherwise NO.
*/
BOOL plcrypto_constant_time_compare (const void *s1, size_t s1len, const void *s2, size_t s2len) {
return plcrypto_constant_time_compare_internal_ptr(s1, s1len, s2, s2len) == 0;
}
/**
* @}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment