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