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.align 6 122.Lck: 123 .long 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269 124 .long 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9 125 .long 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249 126 .long 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9 127 .long 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229 128 .long 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299 129 .long 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209 130 .long 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 131.Lfk: 132 .long 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc 133___ 134}}} 135 136{{{ 137my ($key,$keys)=("x0","x1"); 138my ($tmp)=("x2"); 139my ($key0,$key1,$key2,$key3,$key4,$key5,$key6,$key7)=map("v$_",(0..7)); 140my ($const0,$const1,$const2,$const3,$const4,$const5,$const6,$const7)=map("v$_",(16..23)); 141my ($fkconst) = ("v24"); 142$code.=<<___; 143.globl ${prefix}_set_encrypt_key 144.type ${prefix}_set_encrypt_key,%function 145.align 5 146${prefix}_set_encrypt_key: 147 AARCH64_VALID_CALL_TARGET 148 ld1 {$key0.4s},[$key] 149 adr $tmp,.Lfk 150 ld1 {$fkconst.4s},[$tmp] 151 adr $tmp,.Lck 152 ld1 {$const0.4s,$const1.4s,$const2.4s,$const3.4s},[$tmp],64 153___ 154 &rev32($key0, $key0); 155$code.=<<___; 156 ld1 {$const4.4s,$const5.4s,$const6.4s,$const7.4s},[$tmp] 157 eor $key0.16b,$key0.16b,$fkconst.16b; 158 sm4ekey $key0.4S,$key0.4S,$const0.4S 159 sm4ekey $key1.4S,$key0.4S,$const1.4S 160 sm4ekey $key2.4S,$key1.4S,$const2.4S 161 sm4ekey $key3.4S,$key2.4S,$const3.4S 162 sm4ekey $key4.4S,$key3.4S,$const4.4S 163 st1 {$key0.4s,$key1.4s,$key2.4s,$key3.4s},[$keys],64 164 sm4ekey $key5.4S,$key4.4S,$const5.4S 165 sm4ekey $key6.4S,$key5.4S,$const6.4S 166 sm4ekey $key7.4S,$key6.4S,$const7.4S 167 st1 {$key4.4s,$key5.4s,$key6.4s,$key7.4s},[$keys] 168 ret 169.size ${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key 170___ 171}}} 172 173{{{ 174my ($key,$keys)=("x0","x1"); 175my ($tmp)=("x2"); 176my ($key7,$key6,$key5,$key4,$key3,$key2,$key1,$key0)=map("v$_",(0..7)); 177my ($const0,$const1,$const2,$const3,$const4,$const5,$const6,$const7)=map("v$_",(16..23)); 178my ($fkconst) = ("v24"); 179$code.=<<___; 180.globl ${prefix}_set_decrypt_key 181.type ${prefix}_set_decrypt_key,%function 182.align 5 183${prefix}_set_decrypt_key: 184 AARCH64_VALID_CALL_TARGET 185 ld1 {$key0.4s},[$key] 186 adr $tmp,.Lfk 187 ld1 {$fkconst.4s},[$tmp] 188 adr $tmp, .Lck 189 ld1 {$const0.4s,$const1.4s,$const2.4s,$const3.4s},[$tmp],64 190___ 191 &rev32($key0, $key0); 192$code.=<<___; 193 ld1 {$const4.4s,$const5.4s,$const6.4s,$const7.4s},[$tmp] 194 eor $key0.16b, $key0.16b,$fkconst.16b; 195 sm4ekey $key0.4S,$key0.4S,$const0.4S 196 sm4ekey $key1.4S,$key0.4S,$const1.4S 197 sm4ekey $key2.4S,$key1.4S,$const2.4S 198 rev64 $key0.4s,$key0.4s 199 rev64 $key1.4s,$key1.4s 200 ext $key0.16b,$key0.16b,$key0.16b,#8 201 ext $key1.16b,$key1.16b,$key1.16b,#8 202 sm4ekey $key3.4S,$key2.4S,$const3.4S 203 sm4ekey $key4.4S,$key3.4S,$const4.4S 204 rev64 $key2.4s,$key2.4s 205 rev64 $key3.4s,$key3.4s 206 ext $key2.16b,$key2.16b,$key2.16b,#8 207 ext $key3.16b,$key3.16b,$key3.16b,#8 208 sm4ekey $key5.4S,$key4.4S,$const5.4S 209 sm4ekey $key6.4S,$key5.4S,$const6.4S 210 rev64 $key4.4s,$key4.4s 211 rev64 $key5.4s,$key5.4s 212 ext $key4.16b,$key4.16b,$key4.16b,#8 213 ext $key5.16b,$key5.16b,$key5.16b,#8 214 sm4ekey $key7.4S,$key6.4S,$const7.4S 215 rev64 $key6.4s, $key6.4s 216 rev64 $key7.4s, $key7.4s 217 ext $key6.16b,$key6.16b,$key6.16b,#8 218 ext $key7.16b,$key7.16b,$key7.16b,#8 219 st1 {$key7.4s,$key6.4s,$key5.4s,$key4.4s},[$keys],64 220 st1 {$key3.4s,$key2.4s,$key1.4s,$key0.4s},[$keys] 221 ret 222.size ${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key 223___ 224}}} 225 226{{{ 227sub gen_block () { 228my $dir = shift; 229my ($inp,$out,$rk)=map("x$_",(0..2)); 230my ($data)=("v16"); 231$code.=<<___; 232.globl ${prefix}_${dir}crypt 233.type ${prefix}_${dir}crypt,%function 234.align 5 235${prefix}_${dir}crypt: 236 AARCH64_VALID_CALL_TARGET 237 ld1 {$data.4s},[$inp] 238 ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],64 239 ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk] 240___ 241 &rev32($data,$data); 242 &enc_blk($data); 243 &rev32($data,$data); 244$code.=<<___; 245 st1 {$data.4s},[$out] 246 ret 247.size ${prefix}_${dir}crypt,.-${prefix}_${dir}crypt 248___ 249} 250 251&gen_block("en"); 252&gen_block("de"); 253}}} 254 255{{{ 256my ($inp,$out,$len,$rk)=map("x$_",(0..3)); 257my ($enc) = ("w4"); 258my @dat=map("v$_",(16..23)); 259$code.=<<___; 260.globl ${prefix}_ecb_encrypt 261.type ${prefix}_ecb_encrypt,%function 262.align 5 263${prefix}_ecb_encrypt: 264 AARCH64_VALID_CALL_TARGET 265 ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],#64 266 ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk] 2671: 268 cmp $len,#64 269 b.lt 1f 270 ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp],#64 271 cmp $len,#128 272 b.lt 2f 273 ld1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$inp],#64 274 // 8 blocks 275___ 276 &rev32(@dat[0],@dat[0]); 277 &rev32(@dat[1],@dat[1]); 278 &rev32(@dat[2],@dat[2]); 279 &rev32(@dat[3],@dat[3]); 280 &rev32(@dat[4],@dat[4]); 281 &rev32(@dat[5],@dat[5]); 282 &rev32(@dat[6],@dat[6]); 283 &rev32(@dat[7],@dat[7]); 284 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 285 &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]); 286 &rev32(@dat[0],@dat[0]); 287 &rev32(@dat[1],@dat[1]); 288 &rev32(@dat[2],@dat[2]); 289 &rev32(@dat[3],@dat[3]); 290 &rev32(@dat[4],@dat[4]); 291 &rev32(@dat[5],@dat[5]); 292$code.=<<___; 293 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 294___ 295 &rev32(@dat[6],@dat[6]); 296 &rev32(@dat[7],@dat[7]); 297$code.=<<___; 298 st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64 299 subs $len,$len,#128 300 b.gt 1b 301 ret 302 // 4 blocks 3032: 304___ 305 &rev32(@dat[0],@dat[0]); 306 &rev32(@dat[1],@dat[1]); 307 &rev32(@dat[2],@dat[2]); 308 &rev32(@dat[3],@dat[3]); 309 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 310 &rev32(@dat[0],@dat[0]); 311 &rev32(@dat[1],@dat[1]); 312 &rev32(@dat[2],@dat[2]); 313 &rev32(@dat[3],@dat[3]); 314$code.=<<___; 315 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 316 subs $len,$len,#64 317 b.gt 1b 3181: 319 subs $len,$len,#16 320 b.lt 1f 321 ld1 {@dat[0].4s},[$inp],#16 322___ 323 &rev32(@dat[0],@dat[0]); 324 &enc_blk(@dat[0]); 325 &rev32(@dat[0],@dat[0]); 326$code.=<<___; 327 st1 {@dat[0].4s},[$out],#16 328 b.ne 1b 3291: 330 ret 331.size ${prefix}_ecb_encrypt,.-${prefix}_ecb_encrypt 332___ 333}}} 334 335{{{ 336my ($inp,$out,$len,$rk,$ivp)=map("x$_",(0..4)); 337my ($enc) = ("w5"); 338my @dat=map("v$_",(16..23)); 339my @in=map("v$_",(24..31)); 340my ($ivec) = ("v8"); 341$code.=<<___; 342.globl ${prefix}_cbc_encrypt 343.type ${prefix}_cbc_encrypt,%function 344.align 5 345${prefix}_cbc_encrypt: 346 AARCH64_VALID_CALL_TARGET 347 stp d8,d9,[sp, #-16]! 348 349 ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],#64 350 ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk] 351 ld1 {$ivec.4s},[$ivp] 352 cmp $enc,#0 353 b.eq .Ldec 3541: 355 cmp $len, #64 356 b.lt 1f 357 ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp],#64 358 eor @dat[0].16b,@dat[0].16b,$ivec.16b 359___ 360 &rev32(@dat[1],@dat[1]); 361 &rev32(@dat[0],@dat[0]); 362 &rev32(@dat[2],@dat[2]); 363 &rev32(@dat[3],@dat[3]); 364 &enc_blk(@dat[0]); 365$code.=<<___; 366 eor @dat[1].16b,@dat[1].16b,@dat[0].16b 367___ 368 &enc_blk(@dat[1]); 369 &rev32(@dat[0],@dat[0]); 370$code.=<<___; 371 eor @dat[2].16b,@dat[2].16b,@dat[1].16b 372___ 373 &enc_blk(@dat[2]); 374 &rev32(@dat[1],@dat[1]); 375$code.=<<___; 376 eor @dat[3].16b,@dat[3].16b,@dat[2].16b 377___ 378 &enc_blk(@dat[3]); 379 &rev32(@dat[2],@dat[2]); 380 &rev32(@dat[3],@dat[3]); 381$code.=<<___; 382 mov $ivec.16b,@dat[3].16b 383 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 384 subs $len,$len,#64 385 b.ne 1b 3861: 387 subs $len,$len,#16 388 b.lt 3f 389 ld1 {@dat[0].4s},[$inp],#16 390 eor $ivec.16b,$ivec.16b,@dat[0].16b 391___ 392 &rev32($ivec,$ivec); 393 &enc_blk($ivec); 394 &rev32($ivec,$ivec); 395$code.=<<___; 396 st1 {$ivec.16b},[$out],#16 397 b.ne 1b 398 b 3f 399.Ldec: 4001: 401 cmp $len, #64 402 b.lt 1f 403 ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp] 404 ld1 {@in[0].4s,@in[1].4s,@in[2].4s,@in[3].4s},[$inp],#64 405 cmp $len,#128 406 b.lt 2f 407 // 8 blocks mode 408 ld1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$inp] 409 ld1 {@in[4].4s,@in[5].4s,@in[6].4s,@in[7].4s},[$inp],#64 410___ 411 &rev32(@dat[0],@dat[0]); 412 &rev32(@dat[1],@dat[1]); 413 &rev32(@dat[2],@dat[2]); 414 &rev32(@dat[3],$dat[3]); 415 &rev32(@dat[4],@dat[4]); 416 &rev32(@dat[5],@dat[5]); 417 &rev32(@dat[6],@dat[6]); 418 &rev32(@dat[7],$dat[7]); 419 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 420 &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]); 421 &rev32(@dat[0],@dat[0]); 422 &rev32(@dat[1],@dat[1]); 423 &rev32(@dat[2],@dat[2]); 424 &rev32(@dat[3],@dat[3]); 425 &rev32(@dat[4],@dat[4]); 426 &rev32(@dat[5],@dat[5]); 427 &rev32(@dat[6],@dat[6]); 428 &rev32(@dat[7],@dat[7]); 429$code.=<<___; 430 eor @dat[0].16b,@dat[0].16b,$ivec.16b 431 eor @dat[1].16b,@dat[1].16b,@in[0].16b 432 eor @dat[2].16b,@dat[2].16b,@in[1].16b 433 mov $ivec.16b,@in[7].16b 434 eor @dat[3].16b,$dat[3].16b,@in[2].16b 435 eor @dat[4].16b,$dat[4].16b,@in[3].16b 436 eor @dat[5].16b,$dat[5].16b,@in[4].16b 437 eor @dat[6].16b,$dat[6].16b,@in[5].16b 438 eor @dat[7].16b,$dat[7].16b,@in[6].16b 439 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 440 st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64 441 subs $len,$len,128 442 b.gt 1b 443 b 3f 444 // 4 blocks mode 4452: 446___ 447 &rev32(@dat[0],@dat[0]); 448 &rev32(@dat[1],@dat[1]); 449 &rev32(@dat[2],@dat[2]); 450 &rev32(@dat[3],$dat[3]); 451 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 452 &rev32(@dat[0],@dat[0]); 453 &rev32(@dat[1],@dat[1]); 454 &rev32(@dat[2],@dat[2]); 455 &rev32(@dat[3],@dat[3]); 456$code.=<<___; 457 eor @dat[0].16b,@dat[0].16b,$ivec.16b 458 eor @dat[1].16b,@dat[1].16b,@in[0].16b 459 mov $ivec.16b,@in[3].16b 460 eor @dat[2].16b,@dat[2].16b,@in[1].16b 461 eor @dat[3].16b,$dat[3].16b,@in[2].16b 462 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 463 subs $len,$len,#64 464 b.gt 1b 4651: 466 subs $len,$len,#16 467 b.lt 3f 468 ld1 {@dat[0].4s},[$inp],#16 469 mov @in[0].16b,@dat[0].16b 470___ 471 &rev32(@dat[0],@dat[0]); 472 &enc_blk(@dat[0]); 473 &rev32(@dat[0],@dat[0]); 474$code.=<<___; 475 eor @dat[0].16b,@dat[0].16b,$ivec.16b 476 mov $ivec.16b,@in[0].16b 477 st1 {@dat[0].16b},[$out],#16 478 b.ne 1b 4793: 480 // save back IV 481 st1 {$ivec.16b},[$ivp] 482 ldp d8,d9,[sp],#16 483 ret 484.size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt 485___ 486}}} 487 488{{{ 489my ($inp,$out,$len,$rk,$ivp)=map("x$_",(0..4)); 490my ($ctr)=("w5"); 491my @dat=map("v$_",(16..23)); 492my @in=map("v$_",(24..31)); 493my ($ivec)=("v8"); 494$code.=<<___; 495.globl ${prefix}_ctr32_encrypt_blocks 496.type ${prefix}_ctr32_encrypt_blocks,%function 497.align 5 498${prefix}_ctr32_encrypt_blocks: 499 AARCH64_VALID_CALL_TARGET 500 stp d8,d9,[sp, #-16]! 501 502 ld1 {$ivec.4s},[$ivp] 503 ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],64 504 ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk] 505___ 506 &rev32($ivec,$ivec); 507$code.=<<___; 508 mov $ctr,$ivec.s[3] 5091: 510 cmp $len,#4 511 b.lt 1f 512 ld1 {@in[0].4s,@in[1].4s,@in[2].4s,@in[3].4s},[$inp],#64 513 mov @dat[0].16b,$ivec.16b 514 mov @dat[1].16b,$ivec.16b 515 mov @dat[2].16b,$ivec.16b 516 mov @dat[3].16b,$ivec.16b 517 add $ctr,$ctr,#1 518 mov $dat[1].s[3],$ctr 519 add $ctr,$ctr,#1 520 mov @dat[2].s[3],$ctr 521 add $ctr,$ctr,#1 522 mov @dat[3].s[3],$ctr 523 cmp $len,#8 524 b.lt 2f 525 ld1 {@in[4].4s,@in[5].4s,@in[6].4s,@in[7].4s},[$inp],#64 526 mov @dat[4].16b,$ivec.16b 527 mov @dat[5].16b,$ivec.16b 528 mov @dat[6].16b,$ivec.16b 529 mov @dat[7].16b,$ivec.16b 530 add $ctr,$ctr,#1 531 mov $dat[4].s[3],$ctr 532 add $ctr,$ctr,#1 533 mov @dat[5].s[3],$ctr 534 add $ctr,$ctr,#1 535 mov @dat[6].s[3],$ctr 536 add $ctr,$ctr,#1 537 mov @dat[7].s[3],$ctr 538___ 539 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 540 &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]); 541 &rev32(@dat[0],@dat[0]); 542 &rev32(@dat[1],@dat[1]); 543 &rev32(@dat[2],@dat[2]); 544 &rev32(@dat[3],@dat[3]); 545 &rev32(@dat[4],@dat[4]); 546 &rev32(@dat[5],@dat[5]); 547 &rev32(@dat[6],@dat[6]); 548 &rev32(@dat[7],@dat[7]); 549$code.=<<___; 550 eor @dat[0].16b,@dat[0].16b,@in[0].16b 551 eor @dat[1].16b,@dat[1].16b,@in[1].16b 552 eor @dat[2].16b,@dat[2].16b,@in[2].16b 553 eor @dat[3].16b,@dat[3].16b,@in[3].16b 554 eor @dat[4].16b,@dat[4].16b,@in[4].16b 555 eor @dat[5].16b,@dat[5].16b,@in[5].16b 556 eor @dat[6].16b,@dat[6].16b,@in[6].16b 557 eor @dat[7].16b,@dat[7].16b,@in[7].16b 558 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 559 st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64 560 subs $len,$len,#8 561 b.eq 3f 562 add $ctr,$ctr,#1 563 mov $ivec.s[3],$ctr 564 b 1b 5652: 566___ 567 &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]); 568 &rev32(@dat[0],@dat[0]); 569 &rev32(@dat[1],@dat[1]); 570 &rev32(@dat[2],@dat[2]); 571 &rev32(@dat[3],@dat[3]); 572$code.=<<___; 573 eor @dat[0].16b,@dat[0].16b,@in[0].16b 574 eor @dat[1].16b,@dat[1].16b,@in[1].16b 575 eor @dat[2].16b,@dat[2].16b,@in[2].16b 576 eor @dat[3].16b,@dat[3].16b,@in[3].16b 577 st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64 578 subs $len,$len,#4 579 b.eq 3f 580 add $ctr,$ctr,#1 581 mov $ivec.s[3],$ctr 582 b 1b 5831: 584 subs $len,$len,#1 585 b.lt 3f 586 mov $dat[0].16b,$ivec.16b 587 ld1 {@in[0].4s},[$inp],#16 588___ 589 &enc_blk(@dat[0]); 590 &rev32(@dat[0],@dat[0]); 591$code.=<<___; 592 eor $dat[0].16b,$dat[0].16b,@in[0].16b 593 st1 {$dat[0].4s},[$out],#16 594 b.eq 3f 595 add $ctr,$ctr,#1 596 mov $ivec.s[3],$ctr 597 b 1b 5983: 599 ldp d8,d9,[sp],#16 600 ret 601.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks 602___ 603}}} 604######################################## 605{ my %opcode = ( 606 "sm4e" => 0xcec08400, 607 "sm4ekey" => 0xce60c800); 608 609 sub unsm4 { 610 my ($mnemonic,$arg)=@_; 611 612 $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o 613 && 614 sprintf ".inst\t0x%08x\t//%s %s", 615 $opcode{$mnemonic}|$1|($2<<5)|($3<<16), 616 $mnemonic,$arg; 617 } 618} 619 620open SELF,$0; 621while(<SELF>) { 622 next if (/^#!/); 623 last if (!s/^#/\/\// and !/^$/); 624 print; 625} 626close SELF; 627 628foreach(split("\n",$code)) { 629 s/\`([^\`]*)\`/eval($1)/ge; 630 631 s/\b(sm4\w+)\s+([qv].*)/unsm4($1,$2)/ge; 632 print $_,"\n"; 633} 634 635close STDOUT or die "error closing STDOUT: $!"; 636