1#! /usr/bin/env perl 2# Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. 3# 4# Licensed under the Apache License 2.0 (the "License"). You may not use 5# this file except in compliance with the License. You can obtain a copy 6# in the file LICENSE in the source distribution or at 7# https://www.openssl.org/source/license.html 8 9# 10# This module implements support for SM4 hw support on aarch64 11# Oct 2021 12# 13 14# $output is the last argument if it looks like a file (it has an extension) 15# $flavour is the first argument if it doesn't look like a file 16$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; 17$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; 18 19$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; 20( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or 21( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or 22die "can't locate arm-xlate.pl"; 23 24open OUT,"| \"$^X\" $xlate $flavour \"$output\"" 25 or die "can't call $xlate: $!"; 26*STDOUT=*OUT; 27 28$prefix="sm4_v8"; 29my @rks=map("v$_",(0..7)); 30 31sub rev32() { 32my $dst = shift; 33my $src = shift; 34$code.=<<___; 35#ifndef __ARMEB__ 36 rev32 $dst.16b,$src.16b 37#endif 38___ 39} 40 41sub enc_blk () { 42my $data = shift; 43$code.=<<___; 44 sm4e $data.4s,@rks[0].4s 45 sm4e $data.4s,@rks[1].4s 46 sm4e $data.4s,@rks[2].4s 47 sm4e $data.4s,@rks[3].4s 48 sm4e $data.4s,@rks[4].4s 49 sm4e $data.4s,@rks[5].4s 50 sm4e $data.4s,@rks[6].4s 51 sm4e $data.4s,@rks[7].4s 52 rev64 $data.4S,$data.4S 53 ext $data.16b,$data.16b,$data.16b,#8 54___ 55} 56 57sub enc_4blks () { 58my $data0 = shift; 59my $data1 = shift; 60my $data2 = shift; 61my $data3 = shift; 62$code.=<<___; 63 sm4e $data0.4s,@rks[0].4s 64 sm4e $data1.4s,@rks[0].4s 65 sm4e $data2.4s,@rks[0].4s 66 sm4e $data3.4s,@rks[0].4s 67 68 sm4e $data0.4s,@rks[1].4s 69 sm4e $data1.4s,@rks[1].4s 70 sm4e $data2.4s,@rks[1].4s 71 sm4e $data3.4s,@rks[1].4s 72 73 sm4e $data0.4s,@rks[2].4s 74 sm4e $data1.4s,@rks[2].4s 75 sm4e $data2.4s,@rks[2].4s 76 sm4e $data3.4s,@rks[2].4s 77 78 sm4e $data0.4s,@rks[3].4s 79 sm4e $data1.4s,@rks[3].4s 80 sm4e $data2.4s,@rks[3].4s 81 sm4e $data3.4s,@rks[3].4s 82 83 sm4e $data0.4s,@rks[4].4s 84 sm4e $data1.4s,@rks[4].4s 85 sm4e $data2.4s,@rks[4].4s 86 sm4e $data3.4s,@rks[4].4s 87 88 sm4e $data0.4s,@rks[5].4s 89 sm4e $data1.4s,@rks[5].4s 90 sm4e $data2.4s,@rks[5].4s 91 sm4e $data3.4s,@rks[5].4s 92 93 sm4e $data0.4s,@rks[6].4s 94 sm4e $data1.4s,@rks[6].4s 95 sm4e $data2.4s,@rks[6].4s 96 sm4e $data3.4s,@rks[6].4s 97 98 sm4e $data0.4s,@rks[7].4s 99 rev64 $data0.4S,$data0.4S 100 sm4e $data1.4s,@rks[7].4s 101 ext $data0.16b,$data0.16b,$data0.16b,#8 102 rev64 $data1.4S,$data1.4S 103 sm4e $data2.4s,@rks[7].4s 104 ext $data1.16b,$data1.16b,$data1.16b,#8 105 rev64 $data2.4S,$data2.4S 106 sm4e $data3.4s,@rks[7].4s 107 ext $data2.16b,$data2.16b,$data2.16b,#8 108 rev64 $data3.4S,$data3.4S 109 ext $data3.16b,$data3.16b,$data3.16b,#8 110___ 111} 112 113$code=<<___; 114#include "arm_arch.h" 115.arch armv8-a+crypto 116.text 117___ 118 119{{{ 120$code.=<<___; 121 122.rodata 123.type _${prefix}_consts,%object 124.align 6 125_${prefix}_consts: 126.Lck: 127 .long 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269 128 .long 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9 129 .long 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249 130 .long 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9 131 .long 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229 132 .long 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299 133 .long 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209 134 .long 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 135.Lfk: 136 .long 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc 137.size _${prefix}_consts,.-_${prefix}_consts 138.previous 139 140___ 141}}} 142 143{{{ 144my ($key,$keys)=("x0","x1"); 145my ($tmp)=("x2"); 146my ($key0,$key1,$key2,$key3,$key4,$key5,$key6,$key7)=map("v$_",(0..7)); 147my ($const0,$const1,$const2,$const3,$const4,$const5,$const6,$const7)=map("v$_",(16..23)); 148my ($fkconst) = ("v24"); 149$code.=<<___; 150.globl ${prefix}_set_encrypt_key 151.type ${prefix}_set_encrypt_key,%function 152.align 5 153${prefix}_set_encrypt_key: 154 AARCH64_VALID_CALL_TARGET 155 ld1 {$key0.4s},[$key] 156 adrp $tmp,.Lfk 157 add $tmp,$tmp,#:lo12:.Lfk 158 ld1 {$fkconst.4s},[$tmp] 159 adrp $tmp,.Lck 160 add $tmp,$tmp,#:lo12:.Lck 161 ld1 {$const0.4s,$const1.4s,$const2.4s,$const3.4s},[$tmp],64 162___ 163 &rev32($key0, $key0); 164$code.=<<___; 165 ld1 {$const4.4s,$const5.4s,$const6.4s,$const7.4s},[$tmp] 166 eor $key0.16b,$key0.16b,$fkconst.16b; 167 sm4ekey $key0.4S,$key0.4S,$const0.4S 168 sm4ekey $key1.4S,$key0.4S,$const1.4S 169 sm4ekey $key2.4S,$key1.4S,$const2.4S 170 sm4ekey $key3.4S,$key2.4S,$const3.4S 171 sm4ekey $key4.4S,$key3.4S,$const4.4S 172 st1 {$key0.4s,$key1.4s,$key2.4s,$key3.4s},[$keys],64 173 sm4ekey $key5.4S,$key4.4S,$const5.4S 174 sm4ekey $key6.4S,$key5.4S,$const6.4S 175 sm4ekey $key7.4S,$key6.4S,$const7.4S 176 st1 {$key4.4s,$key5.4s,$key6.4s,$key7.4s},[$keys] 177 ret 178.size ${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key 179___ 180}}} 181 182{{{ 183my ($key,$keys)=("x0","x1"); 184my ($tmp)=("x2"); 185my ($key7,$key6,$key5,$key4,$key3,$key2,$key1,$key0)=map("v$_",(0..7)); 186my ($const0,$const1,$const2,$const3,$const4,$const5,$const6,$const7)=map("v$_",(16..23)); 187my ($fkconst) = ("v24"); 188$code.=<<___; 189.globl ${prefix}_set_decrypt_key 190.type ${prefix}_set_decrypt_key,%function 191.align 5 192${prefix}_set_decrypt_key: 193 AARCH64_VALID_CALL_TARGET 194 ld1 {$key0.4s},[$key] 195 adrp $tmp,.Lfk 196 add $tmp,$tmp,#:lo12:.Lfk 197 ld1 {$fkconst.4s},[$tmp] 198 adrp $tmp,.Lck 199 add $tmp,$tmp,#:lo12:.Lck 200 ld1 {$const0.4s,$const1.4s,$const2.4s,$const3.4s},[$tmp],64 201___ 202 &rev32($key0, $key0); 203$code.=<<___; 204 ld1 {$const4.4s,$const5.4s,$const6.4s,$const7.4s},[$tmp] 205 eor $key0.16b, $key0.16b,$fkconst.16b; 206 sm4ekey $key0.4S,$key0.4S,$const0.4S 207 sm4ekey $key1.4S,$key0.4S,$const1.4S 208 sm4ekey $key2.4S,$key1.4S,$const2.4S 209 rev64 $key0.4s,$key0.4s 210 rev64 $key1.4s,$key1.4s 211 ext $key0.16b,$key0.16b,$key0.16b,#8 212 ext $key1.16b,$key1.16b,$key1.16b,#8 213 sm4ekey $key3.4S,$key2.4S,$const3.4S 214 sm4ekey $key4.4S,$key3.4S,$const4.4S 215 rev64 $key2.4s,$key2.4s 216 rev64 $key3.4s,$key3.4s 217 ext $key2.16b,$key2.16b,$key2.16b,#8 218 ext $key3.16b,$key3.16b,$key3.16b,#8 219 sm4ekey $key5.4S,$key4.4S,$const5.4S 220 sm4ekey $key6.4S,$key5.4S,$const6.4S 221 rev64 $key4.4s,$key4.4s 222 rev64 $key5.4s,$key5.4s 223 ext $key4.16b,$key4.16b,$key4.16b,#8 224 ext $key5.16b,$key5.16b,$key5.16b,#8 225 sm4ekey $key7.4S,$key6.4S,$const7.4S 226 rev64 $key6.4s, $key6.4s 227 rev64 $key7.4s, $key7.4s 228 ext $key6.16b,$key6.16b,$key6.16b,#8 229 ext $key7.16b,$key7.16b,$key7.16b,#8 230 st1 {$key7.4s,$key6.4s,$key5.4s,$key4.4s},[$keys],64 231 st1 {$key3.4s,$key2.4s,$key1.4s,$key0.4s},[$keys] 232 ret 233.size ${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key 234___ 235}}} 236 237{{{ 238sub gen_block () { 239my $dir = shift; 240my ($inp,$out,$rk)=map("x$_",(0..2)); 241my ($data)=("v16"); 242$code.=<<___; 243.globl ${prefix}_${dir}crypt 244.type ${prefix}_${dir}crypt,%function 245.align 5 246${prefix}_${dir}crypt: 247 AARCH64_VALID_CALL_TARGET 248 ld1 {$data.4s},[$inp] 249 ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],64 250 ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk] 251___ 252 &rev32($data,$data); 253 &enc_blk($data); 254 &rev32($data,$data); 255$code.=<<___; 256 st1 {$data.4s},[$out] 257 ret 258.size ${prefix}_${dir}crypt,.-${prefix}_${dir}crypt 259___ 260} 261 262&gen_block("en"); 263&gen_block("de"); 264}}} 265 266{{{ 267my ($inp,$out,$len,$rk)=map("x$_",(0..3)); 268my ($enc) = ("w4"); 269my @dat=map("v$_",(16..23)); 270$code.=<<___; 271.globl ${prefix}_ecb_encrypt 272.type ${prefix}_ecb_encrypt,%function 273.align 5 274${prefix}_ecb_encrypt: 275 AARCH64_VALID_CALL_TARGET 276 ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],#64 277 ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk] 2781: 279 cmp $len,#64 280 b.lt 1f 281 ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp],#64 282 cmp $len,#128 283 b.lt 2f 284 ld1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$inp],#64 285 // 8 blocks 286___ 287 &rev32(@dat[0],@dat[0]); 288 &rev32(@dat[1],@dat[1]); 289 &rev32(@dat[2],@dat[2]); 290 &rev32(@dat[3],@dat[3]); 291 &rev32(@dat[4],@dat[4]); 292 &rev32(@dat[5],@dat[5]); 293 &rev32(@dat[6],@dat[6]); 294 &rev32(@dat[7],@dat[7]); 295 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 296 &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]); 297 &rev32(@dat[0],@dat[0]); 298 &rev32(@dat[1],@dat[1]); 299 &rev32(@dat[2],@dat[2]); 300 &rev32(@dat[3],@dat[3]); 301 &rev32(@dat[4],@dat[4]); 302 &rev32(@dat[5],@dat[5]); 303$code.=<<___; 304 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 305___ 306 &rev32(@dat[6],@dat[6]); 307 &rev32(@dat[7],@dat[7]); 308$code.=<<___; 309 st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64 310 subs $len,$len,#128 311 b.gt 1b 312 ret 313 // 4 blocks 3142: 315___ 316 &rev32(@dat[0],@dat[0]); 317 &rev32(@dat[1],@dat[1]); 318 &rev32(@dat[2],@dat[2]); 319 &rev32(@dat[3],@dat[3]); 320 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 321 &rev32(@dat[0],@dat[0]); 322 &rev32(@dat[1],@dat[1]); 323 &rev32(@dat[2],@dat[2]); 324 &rev32(@dat[3],@dat[3]); 325$code.=<<___; 326 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 327 subs $len,$len,#64 328 b.gt 1b 3291: 330 subs $len,$len,#16 331 b.lt 1f 332 ld1 {@dat[0].4s},[$inp],#16 333___ 334 &rev32(@dat[0],@dat[0]); 335 &enc_blk(@dat[0]); 336 &rev32(@dat[0],@dat[0]); 337$code.=<<___; 338 st1 {@dat[0].4s},[$out],#16 339 b.ne 1b 3401: 341 ret 342.size ${prefix}_ecb_encrypt,.-${prefix}_ecb_encrypt 343___ 344}}} 345 346{{{ 347my ($inp,$out,$len,$rk,$ivp)=map("x$_",(0..4)); 348my ($enc) = ("w5"); 349my @dat=map("v$_",(16..23)); 350my @in=map("v$_",(24..31)); 351my ($ivec) = ("v8"); 352$code.=<<___; 353.globl ${prefix}_cbc_encrypt 354.type ${prefix}_cbc_encrypt,%function 355.align 5 356${prefix}_cbc_encrypt: 357 AARCH64_VALID_CALL_TARGET 358 stp d8,d9,[sp, #-16]! 359 360 ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],#64 361 ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk] 362 ld1 {$ivec.4s},[$ivp] 363 cmp $enc,#0 364 b.eq .Ldec 3651: 366 cmp $len, #64 367 b.lt 1f 368 ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp],#64 369 eor @dat[0].16b,@dat[0].16b,$ivec.16b 370___ 371 &rev32(@dat[1],@dat[1]); 372 &rev32(@dat[0],@dat[0]); 373 &rev32(@dat[2],@dat[2]); 374 &rev32(@dat[3],@dat[3]); 375 &enc_blk(@dat[0]); 376$code.=<<___; 377 eor @dat[1].16b,@dat[1].16b,@dat[0].16b 378___ 379 &enc_blk(@dat[1]); 380 &rev32(@dat[0],@dat[0]); 381$code.=<<___; 382 eor @dat[2].16b,@dat[2].16b,@dat[1].16b 383___ 384 &enc_blk(@dat[2]); 385 &rev32(@dat[1],@dat[1]); 386$code.=<<___; 387 eor @dat[3].16b,@dat[3].16b,@dat[2].16b 388___ 389 &enc_blk(@dat[3]); 390 &rev32(@dat[2],@dat[2]); 391 &rev32(@dat[3],@dat[3]); 392$code.=<<___; 393 mov $ivec.16b,@dat[3].16b 394 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 395 subs $len,$len,#64 396 b.ne 1b 3971: 398 subs $len,$len,#16 399 b.lt 3f 400 ld1 {@dat[0].4s},[$inp],#16 401 eor $ivec.16b,$ivec.16b,@dat[0].16b 402___ 403 &rev32($ivec,$ivec); 404 &enc_blk($ivec); 405 &rev32($ivec,$ivec); 406$code.=<<___; 407 st1 {$ivec.16b},[$out],#16 408 b.ne 1b 409 b 3f 410.Ldec: 4111: 412 cmp $len, #64 413 b.lt 1f 414 ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp] 415 ld1 {@in[0].4s,@in[1].4s,@in[2].4s,@in[3].4s},[$inp],#64 416 cmp $len,#128 417 b.lt 2f 418 // 8 blocks mode 419 ld1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$inp] 420 ld1 {@in[4].4s,@in[5].4s,@in[6].4s,@in[7].4s},[$inp],#64 421___ 422 &rev32(@dat[0],@dat[0]); 423 &rev32(@dat[1],@dat[1]); 424 &rev32(@dat[2],@dat[2]); 425 &rev32(@dat[3],$dat[3]); 426 &rev32(@dat[4],@dat[4]); 427 &rev32(@dat[5],@dat[5]); 428 &rev32(@dat[6],@dat[6]); 429 &rev32(@dat[7],$dat[7]); 430 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 431 &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]); 432 &rev32(@dat[0],@dat[0]); 433 &rev32(@dat[1],@dat[1]); 434 &rev32(@dat[2],@dat[2]); 435 &rev32(@dat[3],@dat[3]); 436 &rev32(@dat[4],@dat[4]); 437 &rev32(@dat[5],@dat[5]); 438 &rev32(@dat[6],@dat[6]); 439 &rev32(@dat[7],@dat[7]); 440$code.=<<___; 441 eor @dat[0].16b,@dat[0].16b,$ivec.16b 442 eor @dat[1].16b,@dat[1].16b,@in[0].16b 443 eor @dat[2].16b,@dat[2].16b,@in[1].16b 444 mov $ivec.16b,@in[7].16b 445 eor @dat[3].16b,$dat[3].16b,@in[2].16b 446 eor @dat[4].16b,$dat[4].16b,@in[3].16b 447 eor @dat[5].16b,$dat[5].16b,@in[4].16b 448 eor @dat[6].16b,$dat[6].16b,@in[5].16b 449 eor @dat[7].16b,$dat[7].16b,@in[6].16b 450 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 451 st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64 452 subs $len,$len,128 453 b.gt 1b 454 b 3f 455 // 4 blocks mode 4562: 457___ 458 &rev32(@dat[0],@dat[0]); 459 &rev32(@dat[1],@dat[1]); 460 &rev32(@dat[2],@dat[2]); 461 &rev32(@dat[3],$dat[3]); 462 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 463 &rev32(@dat[0],@dat[0]); 464 &rev32(@dat[1],@dat[1]); 465 &rev32(@dat[2],@dat[2]); 466 &rev32(@dat[3],@dat[3]); 467$code.=<<___; 468 eor @dat[0].16b,@dat[0].16b,$ivec.16b 469 eor @dat[1].16b,@dat[1].16b,@in[0].16b 470 mov $ivec.16b,@in[3].16b 471 eor @dat[2].16b,@dat[2].16b,@in[1].16b 472 eor @dat[3].16b,$dat[3].16b,@in[2].16b 473 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 474 subs $len,$len,#64 475 b.gt 1b 4761: 477 subs $len,$len,#16 478 b.lt 3f 479 ld1 {@dat[0].4s},[$inp],#16 480 mov @in[0].16b,@dat[0].16b 481___ 482 &rev32(@dat[0],@dat[0]); 483 &enc_blk(@dat[0]); 484 &rev32(@dat[0],@dat[0]); 485$code.=<<___; 486 eor @dat[0].16b,@dat[0].16b,$ivec.16b 487 mov $ivec.16b,@in[0].16b 488 st1 {@dat[0].16b},[$out],#16 489 b.ne 1b 4903: 491 // save back IV 492 st1 {$ivec.16b},[$ivp] 493 ldp d8,d9,[sp],#16 494 ret 495.size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt 496___ 497}}} 498 499{{{ 500my ($inp,$out,$len,$rk,$ivp)=map("x$_",(0..4)); 501my ($ctr)=("w5"); 502my @dat=map("v$_",(16..23)); 503my @in=map("v$_",(24..31)); 504my ($ivec)=("v8"); 505$code.=<<___; 506.globl ${prefix}_ctr32_encrypt_blocks 507.type ${prefix}_ctr32_encrypt_blocks,%function 508.align 5 509${prefix}_ctr32_encrypt_blocks: 510 AARCH64_VALID_CALL_TARGET 511 stp d8,d9,[sp, #-16]! 512 513 ld1 {$ivec.4s},[$ivp] 514 ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],64 515 ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk] 516___ 517 &rev32($ivec,$ivec); 518$code.=<<___; 519 mov $ctr,$ivec.s[3] 5201: 521 cmp $len,#4 522 b.lt 1f 523 ld1 {@in[0].4s,@in[1].4s,@in[2].4s,@in[3].4s},[$inp],#64 524 mov @dat[0].16b,$ivec.16b 525 mov @dat[1].16b,$ivec.16b 526 mov @dat[2].16b,$ivec.16b 527 mov @dat[3].16b,$ivec.16b 528 add $ctr,$ctr,#1 529 mov $dat[1].s[3],$ctr 530 add $ctr,$ctr,#1 531 mov @dat[2].s[3],$ctr 532 add $ctr,$ctr,#1 533 mov @dat[3].s[3],$ctr 534 cmp $len,#8 535 b.lt 2f 536 ld1 {@in[4].4s,@in[5].4s,@in[6].4s,@in[7].4s},[$inp],#64 537 mov @dat[4].16b,$ivec.16b 538 mov @dat[5].16b,$ivec.16b 539 mov @dat[6].16b,$ivec.16b 540 mov @dat[7].16b,$ivec.16b 541 add $ctr,$ctr,#1 542 mov $dat[4].s[3],$ctr 543 add $ctr,$ctr,#1 544 mov @dat[5].s[3],$ctr 545 add $ctr,$ctr,#1 546 mov @dat[6].s[3],$ctr 547 add $ctr,$ctr,#1 548 mov @dat[7].s[3],$ctr 549___ 550 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 551 &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]); 552 &rev32(@dat[0],@dat[0]); 553 &rev32(@dat[1],@dat[1]); 554 &rev32(@dat[2],@dat[2]); 555 &rev32(@dat[3],@dat[3]); 556 &rev32(@dat[4],@dat[4]); 557 &rev32(@dat[5],@dat[5]); 558 &rev32(@dat[6],@dat[6]); 559 &rev32(@dat[7],@dat[7]); 560$code.=<<___; 561 eor @dat[0].16b,@dat[0].16b,@in[0].16b 562 eor @dat[1].16b,@dat[1].16b,@in[1].16b 563 eor @dat[2].16b,@dat[2].16b,@in[2].16b 564 eor @dat[3].16b,@dat[3].16b,@in[3].16b 565 eor @dat[4].16b,@dat[4].16b,@in[4].16b 566 eor @dat[5].16b,@dat[5].16b,@in[5].16b 567 eor @dat[6].16b,@dat[6].16b,@in[6].16b 568 eor @dat[7].16b,@dat[7].16b,@in[7].16b 569 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 570 st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64 571 subs $len,$len,#8 572 b.eq 3f 573 add $ctr,$ctr,#1 574 mov $ivec.s[3],$ctr 575 b 1b 5762: 577___ 578 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 579 &rev32(@dat[0],@dat[0]); 580 &rev32(@dat[1],@dat[1]); 581 &rev32(@dat[2],@dat[2]); 582 &rev32(@dat[3],@dat[3]); 583$code.=<<___; 584 eor @dat[0].16b,@dat[0].16b,@in[0].16b 585 eor @dat[1].16b,@dat[1].16b,@in[1].16b 586 eor @dat[2].16b,@dat[2].16b,@in[2].16b 587 eor @dat[3].16b,@dat[3].16b,@in[3].16b 588 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 589 subs $len,$len,#4 590 b.eq 3f 591 add $ctr,$ctr,#1 592 mov $ivec.s[3],$ctr 593 b 1b 5941: 595 subs $len,$len,#1 596 b.lt 3f 597 mov $dat[0].16b,$ivec.16b 598 ld1 {@in[0].4s},[$inp],#16 599___ 600 &enc_blk(@dat[0]); 601 &rev32(@dat[0],@dat[0]); 602$code.=<<___; 603 eor $dat[0].16b,$dat[0].16b,@in[0].16b 604 st1 {$dat[0].4s},[$out],#16 605 b.eq 3f 606 add $ctr,$ctr,#1 607 mov $ivec.s[3],$ctr 608 b 1b 6093: 610 ldp d8,d9,[sp],#16 611 ret 612.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks 613___ 614}}} 615######################################## 616{ my %opcode = ( 617 "sm4e" => 0xcec08400, 618 "sm4ekey" => 0xce60c800); 619 620 sub unsm4 { 621 my ($mnemonic,$arg)=@_; 622 623 $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o 624 && 625 sprintf ".inst\t0x%08x\t//%s %s", 626 $opcode{$mnemonic}|$1|($2<<5)|($3<<16), 627 $mnemonic,$arg; 628 } 629} 630 631open SELF,$0; 632while(<SELF>) { 633 next if (/^#!/); 634 last if (!s/^#/\/\// and !/^$/); 635 print; 636} 637close SELF; 638 639foreach(split("\n",$code)) { 640 s/\`([^\`]*)\`/eval($1)/ge; 641 642 s/\b(sm4\w+)\s+([qv].*)/unsm4($1,$2)/ge; 643 print $_,"\n"; 644} 645 646close STDOUT or die "error closing STDOUT: $!"; 647