1 /*
2 * Copyright (c) 2019-2020, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <stdint.h>
34 #include <stdbool.h>
35 #include <string.h>
36
37 #include <ti/drivers/cryptoutils/utils/CryptoUtils.h>
38
39 /*
40 * ======== CryptoUtils_buffersMatch ========
41 */
CryptoUtils_buffersMatch(const void * buffer0,const void * buffer1,size_t bufferByteLength)42 bool CryptoUtils_buffersMatch(const void *buffer0,
43 const void *buffer1,
44 size_t bufferByteLength) {
45 uint8_t tempResult = 0;
46 size_t i;
47
48 /* XOR each byte of the buffer together and OR the results.
49 * If the OR'd result is non-zero, the buffers do not match.
50 * There is no branch based on the content of the buffers here to avoid
51 * timing attacks.
52 */
53 for (i = 0; i < bufferByteLength; i++) {
54 tempResult |= ((uint8_t *)buffer0)[i] ^ ((uint8_t *)buffer1)[i];
55 }
56
57 return tempResult == 0 ? true : false;
58 }
59
60 /*
61 * ======== CryptoUtils_buffersMatchWordAligned ========
62 */
CryptoUtils_buffersMatchWordAligned(const uint32_t * buffer0,const uint32_t * buffer1,size_t bufferByteLength)63 bool CryptoUtils_buffersMatchWordAligned(const uint32_t *buffer0,
64 const uint32_t *buffer1,
65 size_t bufferByteLength) {
66 uint32_t tempResult = 0;
67 size_t i;
68
69 /* We could skip the branch and just set tempResult equal to the
70 * statement below for the same effect but this is more explicit.
71 */
72 if (bufferByteLength % sizeof(uint32_t) != 0) {
73 return false;
74 }
75
76 /* XOR each 32-bit word of the buffer together and OR the results.
77 * If the OR'd result is non-zero, the buffers do not match.
78 * There is no branch based on the content of the buffers here to avoid
79 * timing attacks.
80 */
81 for (i = 0; i < bufferByteLength / sizeof(uint32_t); i++) {
82 tempResult |= buffer0[i] ^ buffer1[i];
83 }
84
85 return tempResult == 0 ? true : false;
86 }
87
88 /*
89 * ======== CryptoUtils_reverseBufferBytewise ========
90 */
CryptoUtils_reverseBufferBytewise(void * buffer,size_t bufferByteLength)91 void CryptoUtils_reverseBufferBytewise(void * buffer, size_t bufferByteLength) {
92 uint8_t *bufferLow = buffer;
93 uint8_t *bufferHigh = bufferLow + bufferByteLength - 1;
94 uint8_t tmp;
95
96 while (bufferLow < bufferHigh) {
97 tmp = *bufferLow;
98 *bufferLow = *bufferHigh;
99 *bufferHigh = tmp;
100 bufferLow++;
101 bufferHigh--;
102 }
103 }
104
105 /*
106 * ======== CryptoUtils_reverseCopyPad ========
107 */
CryptoUtils_reverseCopyPad(const void * source,void * destination,size_t sourceLength)108 void CryptoUtils_reverseCopyPad(const void *source,
109 void *destination,
110 size_t sourceLength) {
111 uint32_t i;
112 uint8_t remainder;
113 uint32_t temp;
114 uint8_t *tempBytePointer;
115 const uint8_t *sourceBytePointer;
116
117 remainder = sourceLength % sizeof(uint32_t);
118 temp = 0;
119 tempBytePointer = (uint8_t *)&temp;
120 sourceBytePointer = (uint8_t *)source;
121
122 /* Copy source to destination starting at the end of source and the
123 * beginning of destination.
124 * We assemble each word in byte-reversed order and write one word at a
125 * time since the PKA_RAM requires word-aligned reads and writes.
126 */
127
128 for (i = 0; i < sourceLength / sizeof(uint32_t); i++) {
129 uint32_t sourceOffset = sourceLength - 1 - sizeof(uint32_t) * i;
130
131 tempBytePointer[3] = sourceBytePointer[sourceOffset - 3];
132 tempBytePointer[2] = sourceBytePointer[sourceOffset - 2];
133 tempBytePointer[1] = sourceBytePointer[sourceOffset - 1];
134 tempBytePointer[0] = sourceBytePointer[sourceOffset - 0];
135
136 *((uint32_t *)destination + i) = temp;
137 }
138
139 /* Reset to 0 so we do not have to zero-out individual bytes */
140 temp = 0;
141
142 /* If sourceLength is not a word-multiple, we need to copy over the
143 * remaining bytes and zero pad the word we are writing to PKA_RAM.
144 */
145 if (remainder == 1) {
146
147 tempBytePointer[0] = sourceBytePointer[0];
148
149 /* i is reused from the loop above. This write zero-pads the
150 * destination buffer to word-length.
151 */
152 *((uint32_t *)destination + i) = temp;
153 }
154 else if (remainder == 2) {
155
156 tempBytePointer[0] = sourceBytePointer[1];
157 tempBytePointer[1] = sourceBytePointer[0];
158
159 *((uint32_t *)destination + i) = temp;
160 }
161 else if (remainder == 3) {
162
163 tempBytePointer[0] = sourceBytePointer[2];
164 tempBytePointer[1] = sourceBytePointer[1];
165 tempBytePointer[2] = sourceBytePointer[0];
166
167 *((uint32_t *)destination + i) = temp;
168 }
169
170 }
171