1 /*
  2  * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 /*
 26  * Copyright (c) 2017 Project Nayuki. (MIT License)
 27  * https://www.nayuki.io/page/fast-md5-hash-implementation-in-x86-assembly
 28  *
 29  * Permission is hereby granted, free of charge, to any person obtaining a copy of
 30  * this software and associated documentation files (the "Software"), to deal in
 31  * the Software without restriction, including without limitation the rights to
 32  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 33  * the Software, and to permit persons to whom the Software is furnished to do so,
 34  * subject to the following conditions:
 35  * - The above copyright notice and this permission notice shall be included in
 36  *   all copies or substantial portions of the Software.
 37  * - The Software is provided "as is", without warranty of any kind, express or
 38  *   implied, including but not limited to the warranties of merchantability,
 39  *   fitness for a particular purpose and noninfringement. In no event shall the
 40  *   authors or copyright holders be liable for any claim, damages or other
 41  *   liability, whether in an action of contract, tort or otherwise, arising from,
 42  *   out of or in connection with the Software or the use or other dealings in the
 43  *   Software.
 44  */
 45 
 46 #include "precompiled.hpp"
 47 #include "asm/assembler.hpp"
 48 #include "asm/assembler.inline.hpp"
 49 #include "runtime/stubRoutines.hpp"
 50 #include "macroAssembler_x86.hpp"
 51 
 52 // int com.sun.security.provider.MD5.implCompress0(byte[] b, int ofs)
 53 void MacroAssembler::fast_md5(Register buf, Address state, Address ofs, Address limit, bool multi_block) {
 54 
 55   Label start, done_hash, loop0;
 56 
 57   bind(start);
 58 
 59   bind(loop0);
 60 
 61   // Save hash values for addition after rounds
 62   movptr(rdi, state);
 63   movl(rax, Address(rdi,  0));
 64   movl(rbx, Address(rdi,  4));
 65   movl(rcx, Address(rdi,  8));
 66   movl(rdx, Address(rdi, 12));
 67 
 68 #define FF(r1, r2, r3, r4, k, s, t)              \
 69   movl(rsi, r3);                                 \
 70   addl(r1, Address(buf, k*4));                   \
 71   xorl(rsi, r4);                                 \
 72   andl(rsi, r2);                                 \
 73   xorl(rsi, r4);                                 \
 74   leal(r1, Address(r1, rsi, Address::times_1, t)); \
 75   roll(r1, s);                                   \
 76   addl(r1, r2);
 77 
 78 #define GG(r1, r2, r3, r4, k, s, t)              \
 79   movl(rsi, r4);                                 \
 80   movl(rdi, r4);                                 \
 81   addl(r1, Address(buf, k*4));                   \
 82   notl(rsi);                                     \
 83   andl(rdi, r2);                                 \
 84   andl(rsi, r3);                                 \
 85   orl(rsi, rdi);                                 \
 86   leal(r1, Address(r1, rsi, Address::times_1, t)); \
 87   roll(r1, s);                                   \
 88   addl(r1, r2);
 89 
 90 #define HH(r1, r2, r3, r4, k, s, t)              \
 91   movl(rsi, r3);                                 \
 92   addl(r1, Address(buf, k*4));                   \
 93   xorl(rsi, r4);                                 \
 94   xorl(rsi, r2);                                 \
 95   leal(r1, Address(r1, rsi, Address::times_1, t)); \
 96   roll(r1, s);                                   \
 97   addl(r1, r2);
 98 
 99 #define II(r1, r2, r3, r4, k, s, t)              \
100   movl(rsi, r4);                                 \
101   notl(rsi);                                     \
102   addl(r1, Address(buf, k*4));                   \
103   orl(rsi, r2);                                  \
104   xorl(rsi, r3);                                 \
105   leal(r1, Address(r1, rsi, Address::times_1, t)); \
106   roll(r1, s);                                   \
107   addl(r1, r2);
108 
109   // Round 1
110   FF(rax, rbx, rcx, rdx,  0,  7, 0xd76aa478)
111   FF(rdx, rax, rbx, rcx,  1, 12, 0xe8c7b756)
112   FF(rcx, rdx, rax, rbx,  2, 17, 0x242070db)
113   FF(rbx, rcx, rdx, rax,  3, 22, 0xc1bdceee)
114   FF(rax, rbx, rcx, rdx,  4,  7, 0xf57c0faf)
115   FF(rdx, rax, rbx, rcx,  5, 12, 0x4787c62a)
116   FF(rcx, rdx, rax, rbx,  6, 17, 0xa8304613)
117   FF(rbx, rcx, rdx, rax,  7, 22, 0xfd469501)
118   FF(rax, rbx, rcx, rdx,  8,  7, 0x698098d8)
119   FF(rdx, rax, rbx, rcx,  9, 12, 0x8b44f7af)
120   FF(rcx, rdx, rax, rbx, 10, 17, 0xffff5bb1)
121   FF(rbx, rcx, rdx, rax, 11, 22, 0x895cd7be)
122   FF(rax, rbx, rcx, rdx, 12,  7, 0x6b901122)
123   FF(rdx, rax, rbx, rcx, 13, 12, 0xfd987193)
124   FF(rcx, rdx, rax, rbx, 14, 17, 0xa679438e)
125   FF(rbx, rcx, rdx, rax, 15, 22, 0x49b40821)
126 
127   // Round 2
128   GG(rax, rbx, rcx, rdx,  1,  5, 0xf61e2562)
129   GG(rdx, rax, rbx, rcx,  6,  9, 0xc040b340)
130   GG(rcx, rdx, rax, rbx, 11, 14, 0x265e5a51)
131   GG(rbx, rcx, rdx, rax,  0, 20, 0xe9b6c7aa)
132   GG(rax, rbx, rcx, rdx,  5,  5, 0xd62f105d)
133   GG(rdx, rax, rbx, rcx, 10,  9, 0x02441453)
134   GG(rcx, rdx, rax, rbx, 15, 14, 0xd8a1e681)
135   GG(rbx, rcx, rdx, rax,  4, 20, 0xe7d3fbc8)
136   GG(rax, rbx, rcx, rdx,  9,  5, 0x21e1cde6)
137   GG(rdx, rax, rbx, rcx, 14,  9, 0xc33707d6)
138   GG(rcx, rdx, rax, rbx,  3, 14, 0xf4d50d87)
139   GG(rbx, rcx, rdx, rax,  8, 20, 0x455a14ed)
140   GG(rax, rbx, rcx, rdx, 13,  5, 0xa9e3e905)
141   GG(rdx, rax, rbx, rcx,  2,  9, 0xfcefa3f8)
142   GG(rcx, rdx, rax, rbx,  7, 14, 0x676f02d9)
143   GG(rbx, rcx, rdx, rax, 12, 20, 0x8d2a4c8a)
144 
145   // Round 3
146   HH(rax, rbx, rcx, rdx,  5,  4, 0xfffa3942)
147   HH(rdx, rax, rbx, rcx,  8, 11, 0x8771f681)
148   HH(rcx, rdx, rax, rbx, 11, 16, 0x6d9d6122)
149   HH(rbx, rcx, rdx, rax, 14, 23, 0xfde5380c)
150   HH(rax, rbx, rcx, rdx,  1,  4, 0xa4beea44)
151   HH(rdx, rax, rbx, rcx,  4, 11, 0x4bdecfa9)
152   HH(rcx, rdx, rax, rbx,  7, 16, 0xf6bb4b60)
153   HH(rbx, rcx, rdx, rax, 10, 23, 0xbebfbc70)
154   HH(rax, rbx, rcx, rdx, 13,  4, 0x289b7ec6)
155   HH(rdx, rax, rbx, rcx,  0, 11, 0xeaa127fa)
156   HH(rcx, rdx, rax, rbx,  3, 16, 0xd4ef3085)
157   HH(rbx, rcx, rdx, rax,  6, 23, 0x04881d05)
158   HH(rax, rbx, rcx, rdx,  9,  4, 0xd9d4d039)
159   HH(rdx, rax, rbx, rcx, 12, 11, 0xe6db99e5)
160   HH(rcx, rdx, rax, rbx, 15, 16, 0x1fa27cf8)
161   HH(rbx, rcx, rdx, rax,  2, 23, 0xc4ac5665)
162 
163   // Round 4
164   II(rax, rbx, rcx, rdx,  0,  6, 0xf4292244)
165   II(rdx, rax, rbx, rcx,  7, 10, 0x432aff97)
166   II(rcx, rdx, rax, rbx, 14, 15, 0xab9423a7)
167   II(rbx, rcx, rdx, rax,  5, 21, 0xfc93a039)
168   II(rax, rbx, rcx, rdx, 12,  6, 0x655b59c3)
169   II(rdx, rax, rbx, rcx,  3, 10, 0x8f0ccc92)
170   II(rcx, rdx, rax, rbx, 10, 15, 0xffeff47d)
171   II(rbx, rcx, rdx, rax,  1, 21, 0x85845dd1)
172   II(rax, rbx, rcx, rdx,  8,  6, 0x6fa87e4f)
173   II(rdx, rax, rbx, rcx, 15, 10, 0xfe2ce6e0)
174   II(rcx, rdx, rax, rbx,  6, 15, 0xa3014314)
175   II(rbx, rcx, rdx, rax, 13, 21, 0x4e0811a1)
176   II(rax, rbx, rcx, rdx,  4,  6, 0xf7537e82)
177   II(rdx, rax, rbx, rcx, 11, 10, 0xbd3af235)
178   II(rcx, rdx, rax, rbx,  2, 15, 0x2ad7d2bb)
179   II(rbx, rcx, rdx, rax,  9, 21, 0xeb86d391)
180 
181 #undef FF
182 #undef GG
183 #undef HH
184 #undef II
185 
186   // write hash values back in the correct order
187   movptr(rdi, state);
188   addl(Address(rdi,  0), rax);
189   addl(Address(rdi,  4), rbx);
190   addl(Address(rdi,  8), rcx);
191   addl(Address(rdi, 12), rdx);
192 
193   if (multi_block) {
194     // increment data pointer and loop if more to process
195     addptr(buf, 64);
196     addl(ofs, 64);
197     movl(rsi, ofs);
198     cmpl(rsi, limit);
199     jcc(Assembler::belowEqual, loop0);
200     movptr(rax, rsi); //return ofs
201   }
202 
203   bind(done_hash);
204 }