Compare commits

..

3 Commits

Author SHA1 Message Date
jaspreetsachdev
71fc375a72 Merge pull request #534 from Telecominfraproject/v2.9.0-rc3
V2.9.0 rc3
2023-03-20 12:54:55 -04:00
Jaspreet Sachdev
95bfa265ee Merge remote-tracking branch 'origin/main' into v2.9.0 2023-03-20 12:54:09 -04:00
jaspreetsachdev
fce075bd2c Merge pull request #532 from Telecominfraproject/v2.9.0-rc2
V2.9.0 rc2
2023-03-15 13:00:26 -04:00
8145 changed files with 1215284 additions and 1195938 deletions

View File

@@ -21,16 +21,11 @@ jobs:
strategy:
fail-fast: false
matrix:
target: [ 'cig_wf186h', 'cig_wf186w', 'cig_wf188n', 'cig_wf196', 'cig_wf189', 'cybertan_eww631-a1', 'cybertan_eww631-b1','sonicfi_rap630c-311g', 'sonicfi_rap630w-311g', 'sonicfi_rap630w-211g', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_eap104', 'edgecore_eap105', 'edgecore_eap111', 'edgecore_eap112', 'edgecore_oap101', 'edgecore_oap101-6e', 'edgecore_oap101e', 'edgecore_oap101e-6e', 'hfcl_ion4xe', 'hfcl_ion4xi', 'hfcl_ion4x', 'hfcl_ion4x_2', 'hfcl_ion4x_3', 'hfcl_ion4xi_w', 'hfcl_ion4x_w', 'indio_um-305ax', 'sercomm_ap72tip', 'udaya_a6-id2', 'wallys_dr5018', 'wallys_dr6018', 'wallys_dr6018-v4', 'yuncore_ax820', 'yuncore_ax840', 'yuncore_fap640', 'yuncore_fap650', 'yuncore_fap655' ]
target: ['actiontec_web7200', 'cig_wf188n', 'cig_wf194c4', 'cig_wf196-us', 'cig_wf196-ca', 'cig_wf610d', 'cig_wf660a', 'cig_wf808', 'cybertan_eww622-a1', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_eap104', 'liteon_wpx8324', 'edgecore_ecs4100-12ph', 'edgecore_ecw5211', 'edgecore_ecw5410', 'edgecore_oap100', 'edgecore_ssw2ac2600', 'edgecore_spw2ac1200', 'edgecore_spw2ac1200-lan-poe', 'hfcl_ion4', 'hfcl_ion4xe', 'hfcl_ion4xi', 'hfcl_ion4x', 'hfcl_ion4x_2', 'indio_um-305ac', 'indio_um-305ax', 'indio_um-325ac', 'indio_um-510ac-v3', 'indio_um-550ac', 'indio_um-310ax-v1', 'indio_um-510axp-v1', 'indio_um-510axm-v1', 'linksys_ea6350-v4', 'linksys_e8450-ubi', 'linksys_ea8300', 'meshpp_s618_cp03', 'meshpp_s618_cp01', 'udaya_a5-id2', 'wallys_dr40x9', 'wallys_dr6018', 'wallys_dr6018_v4', 'x64_vm', 'yuncore_ax840', 'yuncore_fap640', 'yuncore_fap650' ]
steps:
- uses: actions/checkout@v3
# Clean unnecessary files to save disk space
- name: clean unncessary files to save space
run: |
docker rmi `docker images -q`
- name: Build image for ${{ matrix.target }}
id: build
run: |

View File

@@ -29,7 +29,7 @@ jobs:
run: |
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
make -j TARGET=${{ matrix.target }} make -j TARGET=${{ matrix.target }}
make -j TARGET=${{ matrix.target }}
- name: Package and upload image for ${{ matrix.target }}
id: package_and_upload_image

28
LICENSE
View File

@@ -1,28 +0,0 @@
BSD 3-Clause License
Copyright (c) 2024, Telecom Infra Project
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,7 +1,17 @@
repo: https://github.com/openwrt/openwrt.git
branch: openwrt-23.05
revision: e92cf0c46ffe3ac7fca936c18577bfb19eb4ce9e
branch: openwrt-21.02
revision: c67509efd7d0c43eb3f622f06c8a31aa28d22f6e
output_dir: ./output
patch_folders:
- patches
- patches/backports/
- patches/base
- patches/wifi
- patches/ath79
- patches/ramips
- patches/ipq40xx
- patches/ipq806x
- patches/ipq807x
- patches/rtkmipsel
- patches/rest
- patches/x86

View File

@@ -1,29 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ble_scan
PKG_VERSION:=1.0
PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/ble_scan
SECTION:=base
CATEGORY:=Utilities
TITLE:=ble_scan
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Package/ble_scan/install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ble_scan $(1)/bin/
endef
define Package/ble_scan/extra_provides
echo "libc.so.6";
endef
$(eval $(call BuildPackage,ble_scan))

View File

@@ -1,47 +0,0 @@
#all: ble_scan
#ble_scan: ble_scan.o
# $(CC) $(LDFLAGS) ble_scan.o -o ble_scan
#blescan.o: ble_scan.c
# $(CC) $(CFLAGS) -c ble_scan.c
#clean:
# rm *.o ble_scan
#
#
# Author: Teunis van Beelen
#
# email: teuniz@protonmail.com
#
#
#CROSS-COMPILE:=../../../../../qsdk/staging_dir/toolchain-arm/bin/arm-openwrt-linux-
#CC:=$(CROSS-COMPILE)gcc
CC = gcc
CFLAGS = -Wall -Wextra -Wshadow -Wformat-nonliteral -Wformat-security -Wtype-limits -O2
objects = rs232.o
all: ble_scan
ble_scan : $(objects) ble_scan.o
$(CC) $(CFLAGS) $(objects) ble_scan.o -o ble_scan
ble_scan.o : ble_scan.c rs232.h
$(CC) $(CFLAGS) -c ble_scan.c -o ble_scan.o
rs232.o : rs232.h rs232.c
$(CC) $(CFLAGS) -c rs232.c -o rs232.o
clean :
$(RM) ble_scan $(objects) ble_scan.o
#
#
#
#

View File

@@ -1,387 +0,0 @@
/**************************************************
file: ble_scan.c
purpose: Send HCI command to do BLE scan
compile with the command: gcc ble_scan.c rs232.c -Wall -Wextra -o2 -o ble_scan
**************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
#include "rs232.h"
#define TX 0
#define RX 1
#define BUF_SIZE 4095
#define FULL_BUF_SIZE BUF_SIZE*4
//#define DEBUG
#ifdef DEBUG
#else
#endif
int print_hex(int mode, unsigned char *buf, int size);
int rx_pkt_parser(unsigned char *buf, int size);
struct rx_packet_h{
unsigned char rxType;
unsigned char rxEventCode;
unsigned char rxDataLen;
unsigned char Event[2];
unsigned char Status;
};
struct event_cmd_st_h{
unsigned char OpCode[2];
unsigned char DataLength;
};
struct event_scn_evnt_rep_h{
unsigned char EventId[4];
unsigned char AdvRptEventType;
unsigned char AddressType;
unsigned char Address[6];
unsigned char PrimaryPHY;
unsigned char SecondaryPHY;
unsigned char AdvSid;
unsigned char TxPower;
unsigned char RSSI;
unsigned char DirectAddrType;
unsigned char DirectAddr[6];
unsigned char PeriodicAdvInt[2];
unsigned char DataLength[2];
//unsigned char *DataPtr;
};
int main()
{
int cport_nr,bdrate,n;
//cport_nr=0, /* /dev/ttyS0 (COM1 on windows) */
//bdrate=9600; /* 9600 baud */
cport_nr=39, /* (ttyMSM1 : 39) */
bdrate=115200; /* 115200 baud */
#ifdef DEBUG
clock_t t;
#endif
char mode[]={'8','N','1',0};
unsigned char buf[BUF_SIZE];
unsigned char full_buf[FULL_BUF_SIZE];
int full_buf_ptr = 0;
unsigned char HCIExt_ResetSystemCmd[] = {0x01, 0x1D, 0xFC, 0x01, 0x00 };
int HCIExt_ResetSystemCmd_length = 5;
unsigned char GAP_DeviceInitCmd[] = {0x01, 0x00, 0xFE, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
int GAP_DeviceInitCmd_length = 12;
unsigned char GapScan_enableCmd[] = {0x01, 0x51, 0xFE, 0x06, 0x00, 0x00, 0xF4, 0x01, 0x28, 0x00 };
int GapScan_enableCmd_length = 10;
if(RS232_OpenComport(cport_nr, bdrate, mode, 0))
{
printf("Can not open comport\n");
return(0);
}
RS232_flushRXTX(cport_nr);
// send reset command
#ifdef DEBUG
t=clock();
print_hex(TX, HCIExt_ResetSystemCmd, HCIExt_ResetSystemCmd_length);
t=clock()-t;
printf("t=%ld\n",t); //60
#else
/* sleep for 60ms */
usleep(60000);
#endif
RS232_SendBuf(cport_nr, HCIExt_ResetSystemCmd, HCIExt_ResetSystemCmd_length);
/* sleep for 1 Second */
#ifdef DEBUG
t=clock();
#endif
usleep(1000000);
#ifdef DEBUG
t=clock()-t;
printf("CLOCKS_PER_SEC=%ld\n",t);
#endif
n = RS232_PollComport(cport_nr, buf, BUF_SIZE);
#ifdef DEBUG
t=clock();
print_hex(RX, buf, n);
t=clock()-t;
printf("t=%ld\n",t);
#else
/* sleep for 300ms */
usleep(300000);
#endif
// send device initial command
#ifdef DEBUG
t=clock();
print_hex(TX, GAP_DeviceInitCmd, GAP_DeviceInitCmd_length);
t=clock()-t;
printf("t=%ld\n",t);
#else
/* sleep for 250 ms */
usleep(250000);
#endif
RS232_SendBuf(cport_nr, GAP_DeviceInitCmd, GAP_DeviceInitCmd_length);
/* sleep for 0.5 Second */
usleep(500000);
n = RS232_PollComport(cport_nr, buf, BUF_SIZE);
#ifdef DEBUG
t=clock();
print_hex(RX, buf, n);
t=clock()-t;
printf("t=%ld\n",t);
#else
/* sleep for 500 ms */
usleep(500000);
#endif
// send scan command
#ifdef DEBUG
t=clock();
print_hex(TX, GapScan_enableCmd, GapScan_enableCmd_length);
t=clock()-t;
printf("t=%ld\n",t);
#else
/* sleep for 30ms */
usleep(30000);
#endif
RS232_SendBuf(cport_nr, GapScan_enableCmd, GapScan_enableCmd_length);
//read scan respone
while (n > 0)
{
/* sleep for 400 mS */
usleep(400000);
n = RS232_PollComport(cport_nr, buf, BUF_SIZE);
#ifdef DEBUG
t=clock();
print_hex(RX, buf, n);
t=clock()-t;
printf("t=%ld\n",t);
#endif
if (full_buf_ptr+n>FULL_BUF_SIZE)
{
#ifdef DEBUG
printf("buffer full. break.\n");
#endif
break;
}
memcpy(full_buf+full_buf_ptr, buf, n);
full_buf_ptr+=n;
#ifdef DEBUG
printf("n:%d, full_buf_ptr:%d\n",n, full_buf_ptr);
#endif
}
#ifdef DEBUG
print_hex(RX, full_buf, full_buf_ptr);
#endif
rx_pkt_parser( full_buf, full_buf_ptr);
#ifdef DEBUG
printf("n:%d, full_buf_ptr:%d\n",n, full_buf_ptr);
#endif
RS232_flushRXTX(cport_nr);
RS232_CloseComport(cport_nr);
return(0);
}
/**************************************************
Print buffer in HEX
**************************************************/
int print_hex(int mode, unsigned char *buf, int size)
{
int ii,jj;
if (mode == TX)
printf("TX: ");
else
printf("RX: ");
for(ii=0,jj=0; ii < size; ii++,jj++)
{
printf("%02X ",buf[ii]);
if (jj==15)
{
printf("\n");
jj = 0;
}
}
printf("\n");
return(0);
}
int rx_pkt_parser(unsigned char *buf, int size)
{
int pkt_index=0;
int pkt_size=0;
int temp_event=0;
int temp_EventId=0;
int total_device_count=0;
char szAddress[18];
struct rx_packet_h *rx_packet;
struct event_scn_evnt_rep_h *event_scn_evnt_rep;
#ifdef DEBUG
int dump_i=0;
unsigned char *pkt_ptr;
#endif
if(size<=0){printf("size error\n");return -1;}
printf("BLE scan start:\n");
rx_packet = (struct rx_packet_h *)(buf);
while(pkt_index<size)
{
#ifdef DEBUG
printf("--------------------------------------------------------------------\n");
printf("-Type : 0x%02X (%s)\n",rx_packet->rxType,rx_packet->rxType==0x4?"Event":"Unknown");
if(rx_packet->rxType!=0x4)
{
printf(" Type unknown, rxType:0x%02X, pkt_index:%d\n",rx_packet->rxType,pkt_index);
}
printf("-EventCode : 0x%02X (%s)\n",rx_packet->rxEventCode,rx_packet->rxEventCode==0xff?"HCI_LE_ExtEvent":"Unknown");
if(rx_packet->rxEventCode!=0xff)
{
printf(" EventCode unknown, rxEventCode:0x%02X, pkt_index:%d\n",rx_packet->rxEventCode,pkt_index);
}
printf("-Data Length : 0x%02X (%d) bytes(s)\n",rx_packet->rxDataLen,rx_packet->rxDataLen);
#endif
temp_event = (rx_packet->Event[1]<<8)+rx_packet->Event[0] ;
#ifdef DEBUG
printf(" Event : 0x%02X%02X (%d) ",rx_packet->Event[1],rx_packet->Event[0],temp_event);
if(temp_event==0x067F)
{
printf("(GAP_HCI_ExtentionCommandStatus)\n");
}
else if(temp_event==0x0600)
{
printf("(GAP_DeviceInitDone)\n");
}
else if(temp_event==0x0613)
{
printf("(GAP_AdvertiserScannerEvent)\n");
}
else
{
printf(" Event unknown, Event:0x%04X, pkt_index:%d\n",temp_event,pkt_index);
}
printf(" Status : 0x%02X (%d) (%s)\n",rx_packet->Status,rx_packet->Status,rx_packet->Status==0?"SUCCESS":"FAIL");
#endif
if(temp_event==0x0613)
{
event_scn_evnt_rep = (struct event_scn_evnt_rep_h *)(&(rx_packet->Status) + 1);
temp_EventId = (event_scn_evnt_rep->EventId[3]<<24) + (event_scn_evnt_rep->EventId[2]<<16) +
(event_scn_evnt_rep->EventId[1]<<8) + (event_scn_evnt_rep->EventId[0]) ;
#ifdef DEBUG
printf(" EventId : 0x%02X%02X%02X%02X (%d) ", event_scn_evnt_rep->EventId[3],
event_scn_evnt_rep->EventId[2],
event_scn_evnt_rep->EventId[1],
event_scn_evnt_rep->EventId[0],temp_EventId);
if(temp_EventId==0x00010000)
{
printf("(GAP_EVT_SCAN_ENABLED)\n");
}
else if(temp_EventId==0x00020000)
{
printf("(GAP_EVT_SCAN_DISABLED)\n");
}
else if(temp_EventId==0x00400000)
{
printf("(GAP_EVT_ADV_REPORT)\n");
}
else
{
printf(" EventId unknown, EventId:0x%08X, pkt_index:%d\n",temp_EventId,pkt_index);
}
#endif
if(temp_EventId==0x00400000)
{
sprintf(szAddress,"%02X:%02X:%02X:%02X:%02X:%02X", event_scn_evnt_rep->Address[5],
event_scn_evnt_rep->Address[4],
event_scn_evnt_rep->Address[3],
event_scn_evnt_rep->Address[2],
event_scn_evnt_rep->Address[1],
event_scn_evnt_rep->Address[0]);
#ifdef DEBUG
printf("%04d", total_device_count);
printf(" Address : %s", szAddress);
printf(" RSSI : 0x%02X (%d)(%d)",event_scn_evnt_rep->RSSI,event_scn_evnt_rep->RSSI,event_scn_evnt_rep->RSSI-256);
#else
printf(" Address: %s RSSI: %d", szAddress, event_scn_evnt_rep->RSSI-256);
#endif
printf("\n");
total_device_count++;
}
}
pkt_size = 3+rx_packet->rxDataLen;
#ifdef DEBUG
pkt_ptr = (unsigned char *)rx_packet;
printf(" <Info > Dump(Rx):");
for(dump_i=0; dump_i < pkt_size; dump_i++)
{
if (dump_i%16==0)
{
printf("\n");
printf("%04x:",dump_i);
}
printf("%02X ",pkt_ptr[dump_i]);
}
printf("\n");
#endif
pkt_index+=pkt_size;
#ifdef DEBUG
printf(" pkt_size:%d, pkt_index:%d\n",pkt_size,pkt_index);
#endif
rx_packet = (struct rx_packet_h *)(&(rx_packet->rxDataLen) + rx_packet->rxDataLen + 1);
}
printf("Total: %d Device found.\n",total_device_count);
return 0;
}

View File

@@ -1,879 +0,0 @@
/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2005 - 2021 Teunis van Beelen
*
* Email: teuniz@protonmail.com
*
***************************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***************************************************************************
*/
/* Last revision: February 9, 2021 */
/* For more info and how to use this library, visit: http://www.teuniz.net/RS-232/ */
#include "rs232.h"
#if defined(__linux__) || defined(__FreeBSD__) /* Linux & FreeBSD */
#define RS232_PORTNR 40
int Cport[RS232_PORTNR],
error;
struct termios new_port_settings,
old_port_settings[RS232_PORTNR];
const char *comports[RS232_PORTNR]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4","/dev/ttyS5",
"/dev/ttyS6","/dev/ttyS7","/dev/ttyS8","/dev/ttyS9","/dev/ttyS10","/dev/ttyS11",
"/dev/ttyS12","/dev/ttyS13","/dev/ttyS14","/dev/ttyS15","/dev/ttyUSB0",
"/dev/ttyUSB1","/dev/ttyUSB2","/dev/ttyUSB3","/dev/ttyUSB4","/dev/ttyUSB5",
"/dev/ttyAMA0","/dev/ttyAMA1","/dev/ttyACM0","/dev/ttyACM1",
"/dev/rfcomm0","/dev/rfcomm1","/dev/ircomm0","/dev/ircomm1",
"/dev/cuau0","/dev/cuau1","/dev/cuau2","/dev/cuau3",
"/dev/cuaU0","/dev/cuaU1","/dev/cuaU2","/dev/cuaU3",
"/dev/ttyMSM0","/dev/ttyMSM1"};
int RS232_OpenComport(int comport_number, int baudrate, const char *mode, int flowctrl)
{
int baudr,
status;
if((comport_number>=RS232_PORTNR)||(comport_number<0))
{
printf("illegal comport number\n");
return(1);
}
switch(baudrate)
{
case 50 : baudr = B50;
break;
case 75 : baudr = B75;
break;
case 110 : baudr = B110;
break;
case 134 : baudr = B134;
break;
case 150 : baudr = B150;
break;
case 200 : baudr = B200;
break;
case 300 : baudr = B300;
break;
case 600 : baudr = B600;
break;
case 1200 : baudr = B1200;
break;
case 1800 : baudr = B1800;
break;
case 2400 : baudr = B2400;
break;
case 4800 : baudr = B4800;
break;
case 9600 : baudr = B9600;
break;
case 19200 : baudr = B19200;
break;
case 38400 : baudr = B38400;
break;
case 57600 : baudr = B57600;
break;
case 115200 : baudr = B115200;
break;
case 230400 : baudr = B230400;
break;
case 460800 : baudr = B460800;
break;
#if defined(__linux__)
case 500000 : baudr = B500000;
break;
case 576000 : baudr = B576000;
break;
case 921600 : baudr = B921600;
break;
case 1000000 : baudr = B1000000;
break;
case 1152000 : baudr = B1152000;
break;
case 1500000 : baudr = B1500000;
break;
case 2000000 : baudr = B2000000;
break;
case 2500000 : baudr = B2500000;
break;
case 3000000 : baudr = B3000000;
break;
case 3500000 : baudr = B3500000;
break;
case 4000000 : baudr = B4000000;
break;
#endif
default : printf("invalid baudrate\n");
return(1);
break;
}
int cbits=CS8,
cpar=0,
ipar=IGNPAR,
bstop=0;
if(strlen(mode) != 3)
{
printf("invalid mode \"%s\"\n", mode);
return(1);
}
switch(mode[0])
{
case '8': cbits = CS8;
break;
case '7': cbits = CS7;
break;
case '6': cbits = CS6;
break;
case '5': cbits = CS5;
break;
default : printf("invalid number of data-bits '%c'\n", mode[0]);
return(1);
break;
}
switch(mode[1])
{
case 'N':
case 'n': cpar = 0;
ipar = IGNPAR;
break;
case 'E':
case 'e': cpar = PARENB;
ipar = INPCK;
break;
case 'O':
case 'o': cpar = (PARENB | PARODD);
ipar = INPCK;
break;
default : printf("invalid parity '%c'\n", mode[1]);
return(1);
break;
}
switch(mode[2])
{
case '1': bstop = 0;
break;
case '2': bstop = CSTOPB;
break;
default : printf("invalid number of stop bits '%c'\n", mode[2]);
return(1);
break;
}
/*
http://pubs.opengroup.org/onlinepubs/7908799/xsh/termios.h.html
http://man7.org/linux/man-pages/man3/termios.3.html
*/
Cport[comport_number] = open(comports[comport_number], O_RDWR | O_NOCTTY | O_NDELAY);
if(Cport[comport_number]==-1)
{
perror("unable to open comport ");
return(1);
}
/* lock access so that another process can't also use the port */
if(flock(Cport[comport_number], LOCK_EX | LOCK_NB) != 0)
{
close(Cport[comport_number]);
perror("Another process has locked the comport.");
return(1);
}
error = tcgetattr(Cport[comport_number], old_port_settings + comport_number);
if(error==-1)
{
close(Cport[comport_number]);
flock(Cport[comport_number], LOCK_UN); /* free the port so that others can use it. */
perror("unable to read portsettings ");
return(1);
}
memset(&new_port_settings, 0, sizeof(new_port_settings)); /* clear the new struct */
new_port_settings.c_cflag = cbits | cpar | bstop | CLOCAL | CREAD;
if(flowctrl)
{
new_port_settings.c_cflag |= CRTSCTS;
}
new_port_settings.c_iflag = ipar;
new_port_settings.c_oflag = 0;
new_port_settings.c_lflag = 0;
new_port_settings.c_cc[VMIN] = 0; /* block untill n bytes are received */
new_port_settings.c_cc[VTIME] = 0; /* block untill a timer expires (n * 100 mSec.) */
cfsetispeed(&new_port_settings, baudr);
cfsetospeed(&new_port_settings, baudr);
error = tcsetattr(Cport[comport_number], TCSANOW, &new_port_settings);
if(error==-1)
{
tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
close(Cport[comport_number]);
flock(Cport[comport_number], LOCK_UN); /* free the port so that others can use it. */
perror("unable to adjust portsettings ");
return(1);
}
/* http://man7.org/linux/man-pages/man4/tty_ioctl.4.html */
if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
{
tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
flock(Cport[comport_number], LOCK_UN); /* free the port so that others can use it. */
perror("unable to get portstatus");
return(1);
}
status |= TIOCM_DTR; /* turn on DTR */
status |= TIOCM_RTS; /* turn on RTS */
if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
{
tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
flock(Cport[comport_number], LOCK_UN); /* free the port so that others can use it. */
perror("unable to set portstatus");
return(1);
}
return(0);
}
int RS232_PollComport(int comport_number, unsigned char *buf, int size)
{
int n;
n = read(Cport[comport_number], buf, size);
if(n < 0)
{
if(errno == EAGAIN) return 0;
}
return(n);
}
int RS232_SendByte(int comport_number, unsigned char byte)
{
int n = write(Cport[comport_number], &byte, 1);
if(n < 0)
{
if(errno == EAGAIN)
{
return 0;
}
else
{
return 1;
}
}
return(0);
}
int RS232_SendBuf(int comport_number, unsigned char *buf, int size)
{
int n = write(Cport[comport_number], buf, size);
if(n < 0)
{
if(errno == EAGAIN)
{
return 0;
}
else
{
return -1;
}
}
return(n);
}
void RS232_CloseComport(int comport_number)
{
int status;
if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
{
perror("unable to get portstatus");
}
status &= ~TIOCM_DTR; /* turn off DTR */
status &= ~TIOCM_RTS; /* turn off RTS */
if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
{
perror("unable to set portstatus");
}
tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
close(Cport[comport_number]);
flock(Cport[comport_number], LOCK_UN); /* free the port so that others can use it. */
}
/*
Constant Description
TIOCM_LE DSR (data set ready/line enable)
TIOCM_DTR DTR (data terminal ready)
TIOCM_RTS RTS (request to send)
TIOCM_ST Secondary TXD (transmit)
TIOCM_SR Secondary RXD (receive)
TIOCM_CTS CTS (clear to send)
TIOCM_CAR DCD (data carrier detect)
TIOCM_CD see TIOCM_CAR
TIOCM_RNG RNG (ring)
TIOCM_RI see TIOCM_RNG
TIOCM_DSR DSR (data set ready)
http://man7.org/linux/man-pages/man4/tty_ioctl.4.html
*/
int RS232_IsDCDEnabled(int comport_number)
{
int status;
ioctl(Cport[comport_number], TIOCMGET, &status);
if(status&TIOCM_CAR) return(1);
else return(0);
}
int RS232_IsRINGEnabled(int comport_number)
{
int status;
ioctl(Cport[comport_number], TIOCMGET, &status);
if(status&TIOCM_RNG) return(1);
else return(0);
}
int RS232_IsCTSEnabled(int comport_number)
{
int status;
ioctl(Cport[comport_number], TIOCMGET, &status);
if(status&TIOCM_CTS) return(1);
else return(0);
}
int RS232_IsDSREnabled(int comport_number)
{
int status;
ioctl(Cport[comport_number], TIOCMGET, &status);
if(status&TIOCM_DSR) return(1);
else return(0);
}
void RS232_enableDTR(int comport_number)
{
int status;
if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
{
perror("unable to get portstatus");
}
status |= TIOCM_DTR; /* turn on DTR */
if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
{
perror("unable to set portstatus");
}
}
void RS232_disableDTR(int comport_number)
{
int status;
if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
{
perror("unable to get portstatus");
}
status &= ~TIOCM_DTR; /* turn off DTR */
if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
{
perror("unable to set portstatus");
}
}
void RS232_enableRTS(int comport_number)
{
int status;
if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
{
perror("unable to get portstatus");
}
status |= TIOCM_RTS; /* turn on RTS */
if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
{
perror("unable to set portstatus");
}
}
void RS232_disableRTS(int comport_number)
{
int status;
if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
{
perror("unable to get portstatus");
}
status &= ~TIOCM_RTS; /* turn off RTS */
if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
{
perror("unable to set portstatus");
}
}
void RS232_flushRX(int comport_number)
{
tcflush(Cport[comport_number], TCIFLUSH);
}
void RS232_flushTX(int comport_number)
{
tcflush(Cport[comport_number], TCOFLUSH);
}
void RS232_flushRXTX(int comport_number)
{
tcflush(Cport[comport_number], TCIOFLUSH);
}
#else /* windows */
#define RS232_PORTNR 32
HANDLE Cport[RS232_PORTNR];
const char *comports[RS232_PORTNR]={"\\\\.\\COM1", "\\\\.\\COM2", "\\\\.\\COM3", "\\\\.\\COM4",
"\\\\.\\COM5", "\\\\.\\COM6", "\\\\.\\COM7", "\\\\.\\COM8",
"\\\\.\\COM9", "\\\\.\\COM10", "\\\\.\\COM11", "\\\\.\\COM12",
"\\\\.\\COM13", "\\\\.\\COM14", "\\\\.\\COM15", "\\\\.\\COM16",
"\\\\.\\COM17", "\\\\.\\COM18", "\\\\.\\COM19", "\\\\.\\COM20",
"\\\\.\\COM21", "\\\\.\\COM22", "\\\\.\\COM23", "\\\\.\\COM24",
"\\\\.\\COM25", "\\\\.\\COM26", "\\\\.\\COM27", "\\\\.\\COM28",
"\\\\.\\COM29", "\\\\.\\COM30", "\\\\.\\COM31", "\\\\.\\COM32"};
char mode_str[128];
int RS232_OpenComport(int comport_number, int baudrate, const char *mode, int flowctrl)
{
if((comport_number>=RS232_PORTNR)||(comport_number<0))
{
printf("illegal comport number\n");
return(1);
}
switch(baudrate)
{
case 110 : strcpy(mode_str, "baud=110");
break;
case 300 : strcpy(mode_str, "baud=300");
break;
case 600 : strcpy(mode_str, "baud=600");
break;
case 1200 : strcpy(mode_str, "baud=1200");
break;
case 2400 : strcpy(mode_str, "baud=2400");
break;
case 4800 : strcpy(mode_str, "baud=4800");
break;
case 9600 : strcpy(mode_str, "baud=9600");
break;
case 19200 : strcpy(mode_str, "baud=19200");
break;
case 38400 : strcpy(mode_str, "baud=38400");
break;
case 57600 : strcpy(mode_str, "baud=57600");
break;
case 115200 : strcpy(mode_str, "baud=115200");
break;
case 128000 : strcpy(mode_str, "baud=128000");
break;
case 256000 : strcpy(mode_str, "baud=256000");
break;
case 500000 : strcpy(mode_str, "baud=500000");
break;
case 921600 : strcpy(mode_str, "baud=921600");
break;
case 1000000 : strcpy(mode_str, "baud=1000000");
break;
case 1500000 : strcpy(mode_str, "baud=1500000");
break;
case 2000000 : strcpy(mode_str, "baud=2000000");
break;
case 3000000 : strcpy(mode_str, "baud=3000000");
break;
default : printf("invalid baudrate\n");
return(1);
break;
}
if(strlen(mode) != 3)
{
printf("invalid mode \"%s\"\n", mode);
return(1);
}
switch(mode[0])
{
case '8': strcat(mode_str, " data=8");
break;
case '7': strcat(mode_str, " data=7");
break;
case '6': strcat(mode_str, " data=6");
break;
case '5': strcat(mode_str, " data=5");
break;
default : printf("invalid number of data-bits '%c'\n", mode[0]);
return(1);
break;
}
switch(mode[1])
{
case 'N':
case 'n': strcat(mode_str, " parity=n");
break;
case 'E':
case 'e': strcat(mode_str, " parity=e");
break;
case 'O':
case 'o': strcat(mode_str, " parity=o");
break;
default : printf("invalid parity '%c'\n", mode[1]);
return(1);
break;
}
switch(mode[2])
{
case '1': strcat(mode_str, " stop=1");
break;
case '2': strcat(mode_str, " stop=2");
break;
default : printf("invalid number of stop bits '%c'\n", mode[2]);
return(1);
break;
}
if(flowctrl)
{
strcat(mode_str, " xon=off to=off odsr=off dtr=on rts=off");
}
else
{
strcat(mode_str, " xon=off to=off odsr=off dtr=on rts=on");
}
/*
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363145%28v=vs.85%29.aspx
http://technet.microsoft.com/en-us/library/cc732236.aspx
https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_dcb
*/
Cport[comport_number] = CreateFileA(comports[comport_number],
GENERIC_READ|GENERIC_WRITE,
0, /* no share */
NULL, /* no security */
OPEN_EXISTING,
0, /* no threads */
NULL); /* no templates */
if(Cport[comport_number]==INVALID_HANDLE_VALUE)
{
printf("unable to open comport\n");
return(1);
}
DCB port_settings;
memset(&port_settings, 0, sizeof(port_settings)); /* clear the new struct */
port_settings.DCBlength = sizeof(port_settings);
if(!BuildCommDCBA(mode_str, &port_settings))
{
printf("unable to set comport dcb settings\n");
CloseHandle(Cport[comport_number]);
return(1);
}
if(flowctrl)
{
port_settings.fOutxCtsFlow = TRUE;
port_settings.fRtsControl = RTS_CONTROL_HANDSHAKE;
}
if(!SetCommState(Cport[comport_number], &port_settings))
{
printf("unable to set comport cfg settings\n");
CloseHandle(Cport[comport_number]);
return(1);
}
COMMTIMEOUTS Cptimeouts;
Cptimeouts.ReadIntervalTimeout = MAXDWORD;
Cptimeouts.ReadTotalTimeoutMultiplier = 0;
Cptimeouts.ReadTotalTimeoutConstant = 0;
Cptimeouts.WriteTotalTimeoutMultiplier = 0;
Cptimeouts.WriteTotalTimeoutConstant = 0;
if(!SetCommTimeouts(Cport[comport_number], &Cptimeouts))
{
printf("unable to set comport time-out settings\n");
CloseHandle(Cport[comport_number]);
return(1);
}
return(0);
}
int RS232_PollComport(int comport_number, unsigned char *buf, int size)
{
int n;
/* added the void pointer cast, otherwise gcc will complain about */
/* "warning: dereferencing type-punned pointer will break strict aliasing rules" */
if(!ReadFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL))
{
return -1;
}
return(n);
}
int RS232_SendByte(int comport_number, unsigned char byte)
{
int n;
if(!WriteFile(Cport[comport_number], &byte, 1, (LPDWORD)((void *)&n), NULL))
{
return(1);
}
if(n<0) return(1);
return(0);
}
int RS232_SendBuf(int comport_number, unsigned char *buf, int size)
{
int n;
if(WriteFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL))
{
return(n);
}
return(-1);
}
void RS232_CloseComport(int comport_number)
{
CloseHandle(Cport[comport_number]);
}
/*
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363258%28v=vs.85%29.aspx
*/
int RS232_IsDCDEnabled(int comport_number)
{
int status;
GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status));
if(status&MS_RLSD_ON) return(1);
else return(0);
}
int RS232_IsRINGEnabled(int comport_number)
{
int status;
GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status));
if(status&MS_RING_ON) return(1);
else return(0);
}
int RS232_IsCTSEnabled(int comport_number)
{
int status;
GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status));
if(status&MS_CTS_ON) return(1);
else return(0);
}
int RS232_IsDSREnabled(int comport_number)
{
int status;
GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status));
if(status&MS_DSR_ON) return(1);
else return(0);
}
void RS232_enableDTR(int comport_number)
{
EscapeCommFunction(Cport[comport_number], SETDTR);
}
void RS232_disableDTR(int comport_number)
{
EscapeCommFunction(Cport[comport_number], CLRDTR);
}
void RS232_enableRTS(int comport_number)
{
EscapeCommFunction(Cport[comport_number], SETRTS);
}
void RS232_disableRTS(int comport_number)
{
EscapeCommFunction(Cport[comport_number], CLRRTS);
}
/*
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363428%28v=vs.85%29.aspx
*/
void RS232_flushRX(int comport_number)
{
PurgeComm(Cport[comport_number], PURGE_RXCLEAR | PURGE_RXABORT);
}
void RS232_flushTX(int comport_number)
{
PurgeComm(Cport[comport_number], PURGE_TXCLEAR | PURGE_TXABORT);
}
void RS232_flushRXTX(int comport_number)
{
PurgeComm(Cport[comport_number], PURGE_RXCLEAR | PURGE_RXABORT);
PurgeComm(Cport[comport_number], PURGE_TXCLEAR | PURGE_TXABORT);
}
#endif
void RS232_cputs(int comport_number, const char *text) /* sends a string to serial port */
{
while(*text != 0) RS232_SendByte(comport_number, *(text++));
}
/* return index in comports matching to device name or -1 if not found */
int RS232_GetPortnr(const char *devname)
{
int i;
char str[32];
#if defined(__linux__) || defined(__FreeBSD__) /* Linux & FreeBSD */
strcpy(str, "/dev/");
#else /* windows */
strcpy(str, "\\\\.\\");
#endif
strncat(str, devname, 16);
str[31] = 0;
for(i=0; i<RS232_PORTNR; i++)
{
if(!strcmp(comports[i], str))
{
return i;
}
}
return -1; /* device not found */
}

View File

@@ -1,85 +0,0 @@
/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2005 - 2021 Teunis van Beelen
*
* Email: teuniz@protonmail.com
*
***************************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***************************************************************************
*/
/* For more info and how to use this library, visit: http://www.teuniz.net/RS-232/ */
#ifndef rs232_INCLUDED
#define rs232_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <string.h>
#if defined(__linux__) || defined(__FreeBSD__)
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <sys/file.h>
#include <errno.h>
#else
#include <windows.h>
#endif
int RS232_OpenComport(int, int, const char *, int);
int RS232_PollComport(int, unsigned char *, int);
int RS232_SendByte(int, unsigned char);
int RS232_SendBuf(int, unsigned char *, int);
void RS232_CloseComport(int);
void RS232_cputs(int, const char *);
int RS232_IsDCDEnabled(int);
int RS232_IsRINGEnabled(int);
int RS232_IsCTSEnabled(int);
int RS232_IsDSREnabled(int);
void RS232_enableDTR(int);
void RS232_disableDTR(int);
void RS232_enableRTS(int);
void RS232_disableRTS(int);
void RS232_flushRX(int);
void RS232_flushTX(int);
void RS232_flushRXTX(int);
int RS232_GetPortnr(const char *);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@@ -25,12 +25,21 @@ define Build/Prepare
endef
define Package/cc2652/install
$(INSTALL_DIR) $(1)/lib/firmware/cc2562
$(INSTALL_BIN) ./files/firmware/* $(1)/lib/firmware/cc2562
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/tisbl.init $(1)/etc/init.d/tisbl
$(INSTALL_DIR) $(1)/etc/tifirmware
$(INSTALL_BIN) ./files/firmware/* $(1)/etc/tifirmware/
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/tisbl $(1)/usr/bin/
$(INSTALL_BIN) ./files/*.sh $(1)/usr/bin/
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_BIN) ./files/tisbl.config $(1)/etc/config/tisbl
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/tisbl.defaults $(1)/etc/uci-defaults
endef
$(eval $(call BuildPackage,cc2652))

View File

@@ -0,0 +1,124 @@
#!/usr/bin/lua
--[[
ByteCnt: 1 1 1 2 1 4
---- --------- ---------- ----- ------ -------
FieldName:Type EventCode DataLength Event Status EventId
--]]
--Type
Command = 0x01
Event = 0x04
--OpCode
GapScan_enable = 0xFE51
--EventCode
HCI_LE_ExtEvent = 0xff
--Status
SUCCESS = 0x00
--Event
GAP_HCI_ExtentionCommandStatus = 0x067F
GAP_AdvertiserScannerEvent = 0x0613
--EventId
GAP_EVT_ADV_REPORT = 0x00400000
GAP_EVT_SCAN_ENABLED = 0x00010000
local write = io.write
function print(...)
local n = select("#",...)
for i = 1,n do
local v = tostring(select(i,...))
write(v)
if i~=n then write'\t' end
end
-- write'\n'
end
function printf(str, ...)
return print(str:format(...))
end
function lshift(x, by)
return x * 2 ^ by
end
function GetUint8(Payload, position)
return string.byte(Payload, position)
end
function GetUint32(Payload, position)
return (lshift(string.byte(Payload, position+3),24) + lshift(string.byte(Payload, position+2),16) + lshift(string.byte(Payload, position+1),8) + string.byte(Payload, position))
end
function GetUint16(Payload, position)
return (lshift(string.byte(Payload, position+1),8) + string.byte(Payload, position))
end
function hexdump(Payload,separator)
for i=1,Payload:len(), 1 do
io.write(string.format("%02X", Payload:byte(i)))
if (i< Payload:len()) then
io.write(separator)
end
end
end
ibeacon_hdr=string.char(0x1A,0xFF,0x4C,0x00,0x02,0x15)
function DumpAdvertiserData(Payload)
--[[
Len(1byte)+Type(1byte)+Data(Len bytes)
--]]
while( Payload:len() > 0 ) do
local Len = GetUint8(Payload,1)
if (GetUint8(Payload,2) == 0xff) then -- manufacturer data
print(" MFR=")
hexdump(Payload:sub(1,Len+1),'')
if (Payload:sub(1,6) == ibeacon_hdr) then
print(" [ibeacon]")
end
end
Payload = string.sub(Payload,Len+2,-1)
end
end
function DumpAdvertiserScannerEvent(Payload)
local Status = GetUint8(Payload,3)
local EventId = GetUint32(Payload,4)
if((EventId==GAP_EVT_ADV_REPORT) and (Status==SUCCESS))
then
local MAC = string.sub(Payload,10,15)
local TxPower = GetUint8(Payload,19)
local RSSI = GetUint8(Payload,20)
printf("MAC=%02X%02X%02X%02X%02X%02X RSI=%d PWR=%d",string.byte(MAC,6),string.byte(MAC,5),string.byte(MAC,4),
string.byte(MAC,3),string.byte(MAC,2),string.byte(MAC,1),RSSI,TxPower)
local DataLength = GetUint16(Payload,30)
DumpAdvertiserData(string.sub(Payload,32,-1))
print("\n")
end
end
function hci_event_paser()
while true do
local Header = io.read(3)
if not Header then break end
local EventType = GetUint8(Header,1)
local EventCode = GetUint8(Header,2)
local DataLength = GetUint8(Header,3)
local Data = io.read(DataLength)
local Event = GetUint16(Data,1)
-- print(EventType,EventCode,DataLength,Event)
if not Data then break end
if(Event==GAP_AdvertiserScannerEvent)
then
DumpAdvertiserScannerEvent(Data)
-- hexdump(ibeacon_hdr)
end
end
end
hci_event_paser()

View File

@@ -0,0 +1,8 @@
#!/bin/sh
com-wr.sh /dev/ttyMSM1 3 "\x01\x1D\xFC\x01\x00" > /dev/null # this command dealy time must >= 3, if small then 3, the following commands will be something wrong
com-wr.sh /dev/ttyMSM1 1 "\x01\x00\xFE\x08\x08\x00\x00\x00\x00\x00\x00\x00" > /dev/null
com-wr.sh /dev/ttyMSM1 1 "\x01\x61\xFE\x02\x01\x02" > /dev/null
com-wr.sh /dev/ttyMSM1 1 "\x01\x61\xFE\x02\x01\x03" > /dev/null
com-wr.sh /dev/ttyMSM1 1 "\x01\x61\xFE\x02\x01\x04" > /dev/null
com-wr.sh /dev/ttyMSM1 1 "\x01\x61\xFE\x02\x01\x05" > /dev/null
com-wr.sh /dev/ttyMSM1 3 "\x01\x51\xFE\x06\x00\x00\xF4\x01\x28\x00" | tee /tmp/blescan.data | ble-scan-rx-parser.sh

View File

@@ -1,13 +0,0 @@
#!/bin/sh
if [ -f /sys/class/gpio/ble_enable/value ]; then
echo 1 > /sys/class/gpio/ble_enable/value
fi
echo 0 > /sys/class/gpio/ble_backdoor/value
echo 1 > /sys/class/gpio/ble_reset/value
echo 0 > /sys/class/gpio/ble_reset/value
sleep 1
echo 1 > /sys/class/gpio/ble_reset/value
sleep 1
echo 1 > /sys/class/gpio/ble_backdoor/value
tisbl /dev/ttyMSM1 115200 2652 /lib/firmware/cc2562/simple_broadcaster_bd9.bin

View File

@@ -1,13 +0,0 @@
#!/bin/sh
if [ -f /sys/class/gpio/ble_enable/value ]; then
echo 1 > /sys/class/gpio/ble_enable/value
fi
echo 0 > /sys/class/gpio/ble_backdoor/value
echo 1 > /sys/class/gpio/ble_reset/value
echo 0 > /sys/class/gpio/ble_reset/value
sleep 1
echo 1 > /sys/class/gpio/ble_reset/value
sleep 1
echo 1 > /sys/class/gpio/ble_backdoor/value
tisbl /dev/ttyMSM1 115200 2652 /lib/firmware/cc2562/ble5_host_test_bd9.bin

View File

@@ -1,10 +0,0 @@
#!/bin/sh
if [ -f /sys/class/gpio/ble_enable/value ]; then
echo 1 > /sys/class/gpio/ble_enable/value
fi
echo 1 > /sys/class/gpio/ble_backdoor/value
echo 1 > /sys/class/gpio/ble_reset/value
sleep 1
echo 1 > /sys/class/gpio/ble_reset/value
sleep 1

View File

@@ -0,0 +1,11 @@
#!/usr/bin/lua
local block = 16
while true do
local bytes = io.read(block)
if not bytes then break end
for b in string.gfind(bytes, ".") do
io.write(string.format("%02X ", string.byte(b)))
end
io.write(string.rep(" ", block - string.len(bytes) + 1))
io.write(string.gsub(bytes, "%c", "."), "\n")
end

View File

@@ -1,28 +1,20 @@
#!/bin/sh
function iBeconScan() {
if [ "$#" -eq 4 ]; then
UUID=$1
MAJOR=$2
MINOR=$3
POWER=$4
else
UUID="\xE2\x0A\x39\xF4\x73\xF5\x4B\xC4\xA1\x2F\x17\xD1\xAD\x07\xA9\x61"
MAJOR="\x01\x23"
MINOR="\x45\x67"
POWER="\xC8"
fi
# script---------------- UUID---------------------------------------------------------------------- MAJOR----- MINOR----- POWER-
#example: ibeacon-broadcaster.sh "\xE2\x0A\x39\xF4\x73\xF5\x4B\xC4\xA1\x2F\x17\xD1\xAD\x07\xA9\x61" "\x01\x23" "\x45\x67" "\xC8"
if [ "$#" -eq 4 ]; then
UUID=$1
MAJOR=$2
MINOR=$3
POWER=$4
else
UUID="\xE2\x0A\x39\xF4\x73\xF5\x4B\xC4\xA1\x2F\x17\xD1\xAD\x07\xA9\x61"
MAJOR="\x01\x23"
MINOR="\x45\x67"
POWER="\xC8"
fi
cc2562-wr.sh /dev/ttyMSM1 3 "\x01\x1D\xFC\x01\x00" > /dev/null # this command dealy time must >= 3, if small then 3, the following commands will be something wrong
cc2562-wr.sh /dev/ttyMSM1 1 "\x01\x00\xFE\x08\x01\x00\x00\x00\x00\x00\x00\x00" > /dev/null
cc2562-wr.sh /dev/ttyMSM1 1 "\x01\x3E\xFE\x15\x12\x00\xA0\x00\x00\xA0\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x7F\x01\x01\x00" > /dev/null
cc2562-wr.sh /dev/ttyMSM1 1 "\x09\x44\xFE\x23\x00\x00\x00\x1E\x00\x02\x01\x1A\x1A\xFF\x4C\x00\x02\x15${UUID}${MAJOR}${MINOR}${POWER}\x00" > /dev/null
cc2562-wr.sh /dev/ttyMSM1 1 "\x01\x3F\xFE\x04\x00\x00\x00\x00"
}
cc2562-reset.sh
while true
do
iBeconScan
sleep 1
done
com-wr.sh /dev/ttyMSM1 3 "\x01\x1D\xFC\x01\x00" > /dev/null # this command dealy time must >= 3, if small then 3, the following commands will be something wrong
com-wr.sh /dev/ttyMSM1 1 "\x01\x00\xFE\x08\x01\x00\x00\x00\x00\x00\x00\x00" > /dev/null
com-wr.sh /dev/ttyMSM1 1 "\x01\x3E\xFE\x15\x12\x00\xA0\x00\x00\xA0\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x7F\x01\x01\x00" > /dev/null
com-wr.sh /dev/ttyMSM1 1 "\x09\x44\xFE\x23\x00\x00\x00\x1E\x00\x02\x01\x1A\x1A\xFF\x4C\x00\x02\x15${UUID}${MAJOR}${MINOR}${POWER}\x00" > /dev/null
com-wr.sh /dev/ttyMSM1 1 "\x01\x3F\xFE\x04\x00\x00\x00\x00" | hexdump.sh

View File

@@ -0,0 +1,5 @@
#!/bin/sh
killall -9 ser2net
tisbl.sh /dev/ttyMSM1 115200 2652 /etc/tifirmware/ble5_host_test_bd9.bin 79 34
echo "7000:telnet:0:/dev/ttyMSM1:115200 8DATABITS NONE 1STOPBIT remctl" > /tmp/ser2net.conf
ser2net -c /tmp/ser2net.conf

View File

@@ -0,0 +1,7 @@
config tisbl 'tisbl'
option firmware '/etc/tifirmware/ble5_host_test_bd9.bin'
option tty '/dev/ttyMSM1'
option tichip '2652'
option baudrate '115200'
option resetpin '79'
option backdoorpin '34'

View File

@@ -0,0 +1,13 @@
#!/bin/sh
. /lib/functions.sh
. /lib/functions/system.sh
board=$(board_name)
case $board in
edgecore,eap104)
uci set tisbl.tisbl.backdoorpin=31
uci set tisbl.tisbl.resetpin=35
;;
esac

View File

@@ -0,0 +1,21 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2007 OpenWrt.org
#start after dbus (60)
START=62
USE_PROCD=1
start_service() {
firmware="$(uci -q get tisbl.tisbl.firmware)"
tty="$(uci -q get tisbl.tisbl.tty)"
tichip="$(uci -q get tisbl.tisbl.tichip)"
baudrate="$(uci -q get tisbl.tisbl.baudrate)"
resetpin="$(uci -q get tisbl.tisbl.resetpin)"
backdoorpin="$(uci -q get tisbl.tisbl.backdoorpin)"
tisbl.sh $tty $baudrate $tichip $firmware $resetpin $backdoorpin
}
service_triggers()
{
procd_add_reload_trigger "tisbl"
}

View File

@@ -0,0 +1,43 @@
#!/bin/sh
# tisbl.sh $tty $baudrate $tichip $firmware $resetpin $backdoorpin
# tisbl.sh /dev/ttyMSM1 115200 2652 /etc/tifirmware/blinky_bd13.bin 79 67
#assumption: resetpin and backdoorpin are low active
tty=$1
baudrate=$2
tichip=$3
firmware=$4
resetpin=$5
backdoorpin=$6
ti_reset() #assumption:resetpin is low active
{
if [ ! -e /sys/class/gpio/gpio${resetpin} ]; then
echo ${resetpin} > /sys/class/gpio/export
fi
echo out > /sys/class/gpio/gpio${resetpin}/direction
echo 1 > /sys/class/gpio/gpio${resetpin}/value
echo 0 > /sys/class/gpio/gpio${resetpin}/value
sleep 1
echo 1 > /sys/class/gpio/gpio${resetpin}/value
}
ti_goto_bootloader() #assumption:backdoorpin is low active
{
if [ ! -e /sys/class/gpio/gpio${backdoorpin} ]; then
echo ${backdoorpin} > /sys/class/gpio/export
fi
echo out > /sys/class/gpio/gpio${backdoorpin}/direction
echo 0 > /sys/class/gpio/gpio${backdoorpin}/value
ti_reset
sleep 1
echo 1 > /sys/class/gpio/gpio${backdoorpin}/value
}
if [ -e $firmware ]; then
ti_goto_bootloader
tisbl $tty $baudrate $tichip $firmware #try to upgrade firmware
fi

View File

@@ -5,8 +5,7 @@ START=80
boot() {
. /lib/functions/system.sh
case $(board_name) in
edgecore,eap102|\
edgecore,oap102)
edgecore,eap102)
echo 54 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio54/direction
echo 0 > /sys/class/gpio/gpio54/value

View File

@@ -1,29 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=eltt2
PKG_VERSION:=1.0
PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/eltt2
SECTION:=base
CATEGORY:=Utilities
TITLE:=eltt2
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Package/eltt2/install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/eltt2 $(1)/bin/
endef
define Package/eltt2/extra_provides
echo "libc.so.6";
endef
$(eval $(call BuildPackage,eltt2))

View File

@@ -1,27 +0,0 @@
Copyright (c) 2014, Infineon Technologies AG
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,15 +0,0 @@
# Makefile for Embedded Linux TPM Toolbox 2 (ELTT2)
# Copyright (c) Infineon Technologies AG
#CROSS-COMPILE:=../../../../../qsdk/staging_dir/toolchain-arm/bin/arm-openwrt-linux-
#CC:=$(CROSS-COMPILE)gcc
CC = gcc
CFLAGS=-Wall -Wextra -std=c99 -g
all: eltt2
eltt2: eltt2.c eltt2.h
$(CC) $(CFLAGS) eltt2.c -o eltt2
clean:
rm -rf eltt2

View File

@@ -1,230 +0,0 @@
# ELTT2 - Infineon Embedded Linux TPM Toolbox 2 for TPM 2.0
All information in this document is Copyright (c) 2014-2022, Infineon Technologies AG <br>
All rights reserved.
# 1. Welcome
Welcome to Embedded Linux TPM Toolbox 2 (ELTT2). ELTT2 is a single-file executable program intended for testing, performing diagnosis and basic state changes of the Infineon Technologies TPM 2.0.
## 1.1 Prerequisites
To build and run ELTT2 you need GCC and a Linux system capable of hosting a TPM.
ELTT2 may run on many other little-endian hardware and software configurations capable of running Linux and hosting a TPM, but this has not been tested.
ELTT2 does not support machines with a big-endian CPU.
## 1.2 Getting Started
A TPM 2.0 evaluation board can be ordered in the [Hitex Webshop](https://www.ehitex.de/evaluation-boards/infineon/2564/iridium-9670-tpm2.0-spi).
<p align="center">
<img src="https://cloud.githubusercontent.com/assets/19730245/25651091/77a84744-2fe1-11e7-91bd-a2e39678202d.JPG" width="350"/>
</p>
In order to execute ELTT2, you need to compile it first:
1. Switch to the directory with the ELTT2 source code
2. Compile the source code by typing the following command:
make
Due to hardware (and thus TPM) access restrictions for normal users, ELTT2 requires root (aka superuser or administrator) privileges. They can be obtained e.g. by using the 'sudo' command on Debian Linux derivates.
The Infineon [TPM 2.0 Application Note](https://www.infineon.com/dgdl/Infineon-App-Note-SLx9670-TPM2.0_Embedded_RPi_DI_SLx-AN-v01_20-EN.pdf?fileId=5546d46267c74c9a01684b96e69f5d7b) shows how the TPM device driver can be set up (e.g. for Linux Kernel 4.14).
# 2. Usage of ELTT2
## 2.1 Generic Usage
ELTT2 is operated as follows:
Call: `./eltt2 <option(s)>`
For example: `./eltt2 -g` or `./eltt2 -gc`
For getting an overview of the possible commands, run `./eltt2 -h`
Some options require the TPM to be in a specific state. This state is shown in brackets ("[]") behind each command line option in the list below:
\[-\]: none <br>
\[\*\]: the TPM platform hierarchy authorization value is not set (i.e., empty buffer) <br>
\[l\]: the required PCR bank is allocated <br>
\[u\]: started <br>
To get the TPM into the required state, call ELTT2 with the corresponding commands ("x" for a state means that whether this state is required or not depends on the actual command or the command parameters sent eventually to the TPM).
Command line option | Explanation | Precondition
--- | --- | ---
`-a [hash algorithm] <data bytes>` | Hash Sequence SHA-1/256/384 \[default: SHA-1\] | \[u\]
`-A <data bytes>` | Hash Sequence SHA-256 | \[u\]
`-b <command bytes>` | Enter your own TPM command | \[u\]
`-c` | Read Clock | \[u\]
`-d <shutdown type>` | Shutdown | \[u\]
`-e [hash algorithm] <PCR index> <PCR digest>` | PCR Extend SHA-1/256/384 \[default: SHA-1\] | \[u\], \[l\]
`-E <PCR index> <PCR digest>` | PCR Extend SHA-256 | \[u\], \[l\]
`-g` | Get fixed capability values | \[u\]
`-v` | Get variable capability values | \[u\]
`-G <data length>` | Get Random | \[u\]
`-h` | Help | \[-\]
`-l <hash algorithm>` | PCR Allocate SHA-1/256/384 | \[u\], \[\*\]
`-r [hash algorithm] <PCR index>` | PCR Read SHA-1/256/384 \[default: SHA-1\] | \[u\], \[l\]
`-R <PCR index>` | PCR Read SHA-256 | \[u\], \[l\]
`-s [hash algorithm] <data bytes>` | Hash SHA-1/256/384 \[default: SHA-1\] | \[u\]
`-S <data bytes>` | Hash SHA-256 | \[u\]
`-t <test type>` | Self Test | \[u\]
`-T` | Get Test Result | \[u\]
`-u <startup type>` | Startup | \[-\]
`-z <PCR index>` | PCR Reset | \[u\]
Additional information:
`-a`: <br>
With the "-a" command you can hash given data with the SHA-1/256/384 hash algorithm. This hash sequence sends 3 commands \[start, update, complete\] to the TPM and allows to hash an arbitrary amount of data. For example, use the following command to hash the byte sequence {0x41, 0x62, 0x43, 0x64}: <br>
`./eltt2 -a 41624364` Hash given data with SHA-1 hash algorithm. <br>
or <br>
`./eltt2 -a sha1 41624364` Hash given data with SHA-1 hash algorithm. <br>
`./eltt2 -a sha256 41624364` Hash given data with SHA-256 hash algorithm. <br>
`./eltt2 -a sha384 41624364` Hash given data with SHA-384 hash algorithm. <br>
`-A`: <br>
With the "-A" command you can hash given data with the SHA-256 hash algorithm. This hash sequence sends 3 commands \[start, update, complete\] to the TPM and allows to hash an arbitrary amount of data. For example, use the following command to hash the byte sequence {0x41, 0x62, 0x43, 0x64}: <br>
`./eltt2 -A 41624364`
`-b`: <br>
With the "-b" command you can enter your own TPM command bytes and read the TPM response. For example, use the following command to send a TPM2_Startup with startup type CLEAR to the TPM: <br>
`./eltt2 -b 80010000000C000001440000`
`-c`: <br>
With the "-c" command you can read the clock values of the TPM.
`-d`: <br>
With the "-d" command you can issue a TPM shutdown. It has 2 options: <br>
`./eltt2 -d` <br>
or <br>
`./eltt2 -d clear` send a TPM2_Shutdown command with shutdown type CLEAR to the TPM. <br>
`./eltt2 -d state` send a TPM2_Shutdown command with shutdown type STATE to the TPM. <br>
`-e`: <br>
With the "-e" command you can extend bytes in the selected PCR with SHA-1/256/384. To do so, you have to enter the index of PCR in hexadecimal that you like to extend and the digest you want to extend the selected PCR with. Note that you can only extend PCRs with index 0 to 16 and PCR 23 and that the digest must have a length of 20/32/48 bytes (will be padded with 0 if necessary). The TPM then builds an SHA-1/256/384 hash over the PCR data in the selected PCR and the digest you provided and writes the result back to the selected PCR. For example, use the following command to extend PCR 23 (0x17) with the byte sequence {0x41, 0x62, 0x43, 0x64, 0x00, ... (will be filled with 0x00)}: <br>
`./eltt2 -e 17 41624364` Extend bytes in PCR 23 with SHA-1. <br>
or <br>
`./eltt2 -e sha1 17 41624364` Extend bytes in PCR 23 with SHA-1. <br>
`./eltt2 -e sha256 17 41624364` Extend bytes in PCR 23 with SHA-256. <br>
`./eltt2 -e sha384 17 41624364` Extend bytes in PCR 23 with SHA-384. <br>
`-E`: <br>
With the "-E" command you can extend bytes in the selected PCR with SHA-256. To do so, you have to enter the index of PCR in hexadecimal that you like to extend and the digest you want to extend the selected PCR with. Note that you can only extend PCRs with index 0 to 16 and PCR 23 and that the digest must have a length of 32 bytes (will be padded with 0 if necessary). The TPM then builds an SHA-256 hash over the PCR data in the selected PCR and the digest you provided and writes the result back to the selected PCR. For example, use the following command to extend PCR 23 (0x17) with the byte sequence {0x41, 0x62, 0x43, 0x64, 0x00, ... (will be filled with 0x00)}: <br>
`./eltt2 -E 17 41624364`
`-g`: <br>
With the "-g" command you can read the TPM's fixed properties.
`-v`: <br>
With the "-v" command you can read the TPM's variable properties.
`-G`: <br>
With the "-G" command you can get a given amount of random bytes. Note that you can only request a maximum amount of 32 random bytes at once. For example, use the following command to get 20 (0x14) random bytes: <br>
`./eltt2 -G 14`
`-l`: <br>
With the "-l" command you can allocate the SHA-1/256/384 PCR bank. Take note of two things. Firstly, the command requires a platform authorization value and it is set to an empty buffer; hence the command cannot be used if the TPM platform authorization value is set (e.g., by UEFI). Secondly, when the command is executed successfully a TPM reset has to follow for it to take effect. For example, use the following command to allocate a PCR bank: <br>
`./eltt2 -l sha1` Allocate SHA-1 PCR bank. <br>
`./eltt2 -l sha256` Allocate SHA-256 PCR bank. <br>
`./eltt2 -l sha384` Allocate SHA-384 PCR bank. <br>
`-r`: <br>
With the "-r" command you can read data from a selected SHA-1/256/384 PCR. For example, use the following command to read data from PCR 23 (0x17): <br>
`./eltt2 -r 17` Read data from SHA-1 PCR 23. <br>
or <br>
`./eltt2 -r sha1 17` Read data from SHA-1 PCR 23. <br>
`./eltt2 -r sha256 17` Read data from SHA-256 PCR 23. <br>
`./eltt2 -r sha384 17` Read data from SHA-384 PCR 23. <br>
`-R`: <br>
With the "-R" command you can read data from a selected SHA-256 PCR. For example, use the following command to read data from PCR 23 (0x17): <br>
`./eltt2 -R 17`
`-s`: <br>
With the "-s" command you can hash given data with the SHA-1/256/384 hash algorithm. This command only allows a limited amount of data to be hashed (depending on the TPM's maximum input buffer size). For example, use the following command to hash the byte sequence {0x41, 0x62, 0x43, 0x64}: <br>
`./eltt2 -s 41624364` Hash given data with SHA-1 hash algorithm. <br>
or <br>
`./eltt2 -s sha1 41624364` Hash given data with SHA-1 hash algorithm. <br>
`./eltt2 -s sha256 41624364` Hash given data with SHA-256 hash algorithm. <br>
`./eltt2 -s sha384 41624364` Hash given data with SHA-384 hash algorithm. <br>
`-S`: <br>
With the "-S" command you can hash given data with the SHA-256 hash algorithm. This command only allows a limited amount of data to be hashed (depending on the TPM input buffer size). For example, use the following command to hash the byte sequence {0x41, 0x62, 0x43, 0x64}: <br>
`./eltt2 -S 41624364`
`-t`: <br>
With the "-t" command you can issue a TPM selftest. It has 3 options: <br>
`./eltt2 -t` <br>
or<br>
`./eltt2 -t not_full` Perform a partial TPM2_Selftest to test previously untested TPM capabilities. <br>
`./eltt2 -t full` Perform a full TPM2_Selftest to test all TPM capabilities. <br>
`./eltt2 -t incremental` Perform a test of selected algorithms.
`-T`: <br>
With the "-T" command you can read the results of a previously run selftest.
`-u`: <br>
With the "-u" command you can issue a TPM startup command. It has 2 options: <br>
`./eltt2 -u` <br>
or <br>
`./eltt2 -u clear` send a TPM2_Startup with startup type CLEAR to the TPM. <br>
`./eltt2 -u state` send a TPM2_Startup with startup type STATE to the TPM.
`-z`: <br>
With the "-z" command you can reset a selected PCR. Note that you can only reset PCRs 16 and 23. For example, use the following command to reset PCR 23 (0x17): <br>
`./eltt2 -z 17`
## 2.2 Examples:
In order to work with the TPM, perform the following steps:
- Send the TPM2_Startup command: `./eltt2 -u`
# 3. If you have questions
If you have any questions or problems, please read the section "FAQ and
Troubleshooting" in this document.
In case you still have questions, contact your local Infineon
Representative.
Further information is available at <https://www.infineon.com/tpm>.
# 4. FAQ and Troubleshooting
If you encounter any error, please make sure that
- the TPM is properly connected.
- the TPM driver is loaded, i.e. check that "/dev/tpm0" exists. In case of driver loading problems (e.g. shown by "Error opening device"), reboot your system and try to load the driver again.
- ELTT2 has been started with root permissions. Please note that ELTT2 needs root permissions for all commands.
- the TPM is started. (See section 2.2 in this document on how to do this.)
The following list shows the most common errors and their solution:
The ELTT2 response is "Error opening the device.":
- You need to load a TPM driver before you can work with ELTT2.
- You need to start ELTT2 with root permissions.
The ELTT2 responds with error code 0x100.
- You need to send the TPM2_Startup command, or you did send it twice. In
case you have not sent it yet, do so with `./eltt2 -u`.
The TPM does not change any of the permanent flags shown by sending the "-g"
command , e.g. after a force clear.
- The TPM requires a reset in order to change any of the permanent flags.
Press the reset button or disconnect the TPM to do so.
The value of a PCR does not change after sending PCR extend or reset.
- With the application permissions you cannot modify every PCR. For more
details, please refer to the description for the different PCR commands
in this file.

View File

@@ -1,362 +0,0 @@
--------------------------------------------------------------------------------
Infineon Embedded Linux TPM Toolbox 2 (ELTT2) for TPM 2.0 v1.1
Infineon Technologies AG
All information in this document is Copyright (c) 2014, Infineon Technologies AG
All rights reserved.
--------------------------------------------------------------------------------
Contents:
1. Welcome
1.1 Prerequisites
1.2 Contents of the package
1.3 Getting Started
2. Usage of Embedded Linux TPM Toolbox 2 (ELTT2)
2.1 Generic Usage
2.2 Examples
3. If you have questions
4. Release Info
5. FAQ
================================================================================
1. Welcome
Welcome to Embedded Linux TPM Toolbox 2 (ELTT2).
ELTT2 is a single-file executable program intended for testing, performing
diagnosis and basic state changes of the Infineon Technologies TPM 2.0.
1.1 Prerequisites
To build and run ELTT2 you need GCC and a Linux system capable of hosting a
TPM 2.0.
Tested PC Platforms (x86):
- Ubuntu (R) Linux 12.04 LTS - 64 bit (modified Kernel 3.15.4)
with Infineon TPM 2.0 SLB9665 Firmware 5.22
Tested Embedded Platforms (ARM):
- Android 6.0 "Marshmallow" - 64 bit (modified Kernel 3.18.0+) on HiKey
with Prototype Infineon I2C TPM 2.0 for Embedded Platforms
ELTT2 may run on many other little-endian hardware and software
configurations capable of running Linux and hosting a TPM 2.0, but this has
not been tested.
ELTT2 does not support machines with a big-endian CPU.
1.2 Contents of Package
ELTT2 consists of the following files:
- eltt2.c
Contains all method implementations of ELTT2.
- eltt2.h
Contains all constant definitions, method and command byte declarations
for the operation of ELTT2.
- License.txt
Contains the license agreement for ELTT2.
- Makefile
Contains the command to compile ELTT2.
- README.txt
This file.
1.3 Getting Started
In order to execute ELTT2, you need to compile it first:
1. Switch to the directory with the ELTT2 source code
2. Compile the source code by typing the following command:
make
Due to hardware (and thus TPM) access restrictions for normal users, ELTT2
requires root (aka superuser or administrator) privileges. They can be
obtained e.g. by using the 'sudo' command on Debian Linux derivates.
2. Usage of ELTT2
2.1 Generic Usage
ELTT2 is operated as follows:
Call: ./eltt2 <option(s)>
For example: ./eltt2 -g or ./eltt2 -gc
For getting an overview of the possible commands, run ./eltt2 -h
Some options require the TPM to be in a specific state. This state is shown
in brackets ("[]") behind each command line option in the list below:
[-]: none
[*]: the TPM platform hierarchy authorization value is not set (i.e., empty buffer)
[l]: the required PCR bank is allocated
[u]: started
To get the TPM into the required state, call ELTT2 with the corresponding
commands ("x" for a state means that whether this state is required or not
depends on the actual command or the command parameters sent eventually to
the TPM).
Command line options: Preconditions:
-a [hash algorithm] <data bytes>: Hash Sequence SHA-1/256/384 [default: SHA-1] [u]
-A <data bytes>: Hash Sequence SHA-256 [u]
-b <command bytes>: Enter your own TPM command [u]
-c: Read Clock [u]
-d <shutdown type>: Shutdown [u]
-e [hash algorithm] <PCR index> <PCR digest>: PCR Extend SHA-1/256/384 [default: SHA-1] [u], [l]
-E <PCR index> <PCR digest>: PCR Extend SHA-256 [u], [l]
-g: Get fixed capability values [u]
-v: Get variable capability values [u]
-G <data length>: Get Random [u]
-h: Help [-]
-l <hash algorithm>: PCR Allocate SHA-1/256/384 [u], [*]
-r [hash algorithm] <PCR index>: PCR Read SHA-1/256/384 [default: SHA-1] [u], [l]
-R <PCR index>: PCR Read SHA-256 [u], [l]
-s [hash algorithm] <data bytes>: Hash SHA-1/SHA256 [default: SHA-1] [u]
-S <data bytes>: Hash SHA-256 [u]
-t <test type>: Self Test [u]
-T: Get Test Result [u]
-u <startup type>: Startup [-]
-z <PCR index>: PCR Reset [u]
Additional information:
-a:
With the "-a" command you can hash given data with the SHA-1/256/384 hash
algorithm. This hash sequence sends 3 commands [start, update, complete]
to the TPM and allows to hash an arbitrary amount of data.
For example, use the following command to hash the byte sequence {0x41,
0x62, 0x43, 0x64}:
./eltt2 -a 41624364 Hash given data with SHA-1 hash algorithm.
or
./eltt2 -a sha1 41624364 Hash given data with SHA-1 hash algorithm.
./eltt2 -a sha256 41624364 Hash given data with SHA-256 hash algorithm.
-A:
With the "-A" command you can hash given data with the SHA-256 hash
algorithm. This hash sequence sends 3 commands [start, update, complete] to
the TPM and allows to hash an arbitrary amount of data.
For example, use the following command to hash the byte sequence {0x41,
0x62, 0x43, 0x64}:
./eltt2 -A 41624364
-b:
With the "-b" command you can enter your own TPM command bytes and read the
TPM response.
For example, use the following command to send a TPM2_Startup with startup
type CLEAR to the TPM:
./eltt2 -b 80010000000C000001440000
-c:
With the "-c" command you can read the clock values of the TPM.
-d:
With the "-d" command you can issue a TPM shutdown. It has 2 options:
./eltt2 -d
or
./eltt2 -d clear send a TPM2_Shutdown command with shutdown type CLEAR to
the TPM.
./eltt2 -d state send a TPM2_Shutdown command with shutdown type STATE to
the TPM.
-e:
With the "-e" command you can extend bytes in the selected PCR with SHA-1/256/384.
To do so, you have to enter the index of PCR in hexadecimal that you like to
extend and the digest you want to extend the selected PCR with. Note that
you can only extend PCRs with index 0 to 16 and PCR 23 and that the digest
must have a length of 20/32/48 bytes (will be padded with 0 if necessary).
The TPM then builds an SHA-1/256/384 hash over the PCR data in the selected PCR
and the digest you provided and writes the result back to the selected PCR.
For example, use the following command to extend PCR 23 (0x17) with the byte
sequence {0x41, 0x62, 0x43, 0x64, 0x00, ... (will be filled with 0x00)}:
./eltt2 -e 17 41624364 Extend bytes in PCR 23 with SHA-1.
or
./eltt2 -e sha1 17 41624364 Extend bytes in PCR 23 with SHA-1.
./eltt2 -e sha256 17 41624364 Extend bytes in PCR 23 with SHA-256.
-E:
With the "-E" command you can extend bytes in the selected PCR with SHA-256.
To do so, you have to enter the index of PCR in hexadecimal that you like to
extend and the digest you want to extend the selected PCR with. Note that
you can only extend PCRs with index 0 to 16 and PCR 23 and that the digest
must have a length of 32 bytes (will be padded with 0 if necessary).
The TPM then builds an SHA-256 hash over the PCR data in the selected PCR
and the digest you provided and writes the result back to the selected PCR.
For example, use the following command to extend PCR 23 (0x17) with the byte
sequence {0x41, 0x62, 0x43, 0x64, 0x00, ... (will be filled with 0x00)}:
./eltt2 -E 17 41624364
-g:
With the "-g" command you can read the TPM's fixed properties.
-v:
With the "-v" command you can read the TPM's variable properties.
-G:
With the "-G" command you can get a given amount of random bytes. Note that
you can only request a maximum amount of 32 random bytes at once.
For example, use the following command to get 20 (0x14) random bytes:
./eltt2 -G 14
-l:
With the "-l" command you can allocate the SHA-1/256/384 PCR bank.
Take note of two things. Firstly, the command requires a platform
authorization value and it is set to an empty buffer; hence the command
cannot be used if the TPM platform authorization value is set (e.g., by UEFI).
Secondly, when the command is executed successfully a TPM reset has to
follow for it to take effect. For example, use the following command to
allocate a PCR bank:
./eltt2 -l sha1 Allocate SHA-1 PCR bank.
./eltt2 -l sha256 Allocate SHA-256 PCR bank.
./eltt2 -l sha384 Allocate SHA-384 PCR bank.
-r:
With the "-r" command you can read data from a selected SHA-1/256/384 PCR.
For example, use the following command to read data from PCR 23 (0x17):
./eltt2 -r 17 Read data from SHA-1 PCR 23.
or
./eltt2 -r sha1 17 Read data from SHA-1 PCR 23.
./eltt2 -r sha256 17 Read data from SHA-256 PCR 23.
-R:
With the "-R" command you can read data from a selected SHA-256 PCR.
For example, use the following command to read data from PCR 23 (0x17):
./eltt2 -R 17
-s:
With the "-s" command you can hash given data with the SHA-1/256/384 hash
algorithm. This command only allows a limited amount of data to be hashed
(depending on the TPM's maximum input buffer size).
For example, use the following command to hash the byte sequence {0x41,
0x62, 0x43, 0x64}:
./eltt2 -s 41624364 Hash given data with SHA-1 hash algorithm.
or
./eltt2 -s sha1 41624364 Hash given data with SHA-1 hash algorithm.
./eltt2 -s sha256 41624364 Hash given data with SHA-256 hash algorithm.
-S:
With the "-S" command you can hash given data with the SHA-256 hash
algorithm. This command only allows a limited amount of data to be hashed
(depending on the TPM input buffer size).
For example, use the following command to hash the byte sequence {0x41,
0x62, 0x43, 0x64}:
./eltt2 -S 41624364
-t:
With the "-t" command you can issue a TPM selftest. It has 3 options:
./eltt2 -t
or
./eltt2 -t not_full Perform a partial TPM2_Selftest to test previously
untested TPM capabilities.
./eltt2 -t full Perform a full TPM2_Selftest to test all TPM
capabilities.
./eltt2 -t incremental Perform a test of selected algorithms.
-T:
With the "-T" command you can read the results of a previously run selftest.
-u:
With the "-u" command you can issue a TPM startup command. It has 2 options:
./eltt2 -u
or
./eltt2 -u clear send a TPM2_Startup with startup type CLEAR to the TPM.
./eltt2 -u state send a TPM2_Startup with startup type STATE to the TPM.
-z:
With the "-z" command you can reset a selected PCR. Note that you can only
reset PCRs 16 and 23 and that the PCR is going to be reset in both banks
(SHA-1 and SHA-256).
For example, use the following command to reset PCR 23 (0x17):
./eltt2 -z 17
2.2 Examples:
In order to work with the TPM, perform the following steps:
- Send the TPM2_Startup command: ./eltt2 -u
3. If you have questions
If you have any questions or problems, please read the section "FAQ and
Troubleshooting" in this document.
In case you still have questions, contact your local Infineon
Representative.
Further information is available at http://www.infineon.com/tpm.
4. Release Info
This is version 1.1. This version is a general release.
5. FAQ and Troubleshooting
If you encounter any error, please make sure that
- the TPM is properly connected.
- the TPM driver is loaded, i.e. check that "/dev/tpm0" exists. In case of
driver loading problems (e.g. shown by "Error opening device"), reboot
your system and try to load the driver again.
- ELTT2 has been started with root permissions. Please note that ELTT2 needs
root permissions for all commands.
- the TPM is started. (See section 2.2 in this document on how to do this.)
- Trousers do not run anymore. In some cases the Kernel starts Trousers by
booting.
Shut down Trousers by entering the following command:
sudo pkill tcsd
The following list shows the most common errors and their solution:
The ELTT2 response is "Error opening the device.":
- You need to load a TPM driver before you can work with ELTT2.
- You need to start ELTT2 with root permissions.
The ELTT2 responds with error code 0x100.
- You need to send the TPM2_Startup command, or you did send it twice. In
case you have not sent it yet, do so with "./eltt2 -u".
The TPM does not change any of the permanent flags shown by sending the "-g"
command , e.g. after a force clear.
- The TPM requires a reset in order to change any of the permanent flags.
Press the reset button or disconnect the TPM to do so.
The value of a PCR does not change after sending PCR extend or reset.
- With the application permissions you cannot modify every PCR. For more
details, please refer to the description for the different PCR commands
in this file.

File diff suppressed because it is too large Load Diff

View File

@@ -1,634 +0,0 @@
#ifndef _ELTT2_H_
#define _ELTT2_H_
/**
* @brief Infineon Embedded Linux TPM Toolbox 2 (ELTT2) for TPM 2.0
* @details eltt2.h implements all TPM byte commands and the prototype declarations for eltt2.c.
* @file eltt2.h
* @date 2014/06/26
* @copyright Copyright (c) 2014 - 2017 Infineon Technologies AG ( www.infineon.com ).\n
* All rights reserved.\n
* \n
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:\n
* \n
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.\n
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.\n
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.\n
* \n
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// this is the main page for doxygen documentation.
/** @mainpage Infineon Embedded Linux TPM Toolbox 2 (ELTT2) for TPM 2.0 Documentation
*
* @section Welcome
* Welcome to Infineon TPM 2.0 Software-Tool "Embedded Linux TPM Toolbox 2 (ELTT2)".\n
* \n
* @section Introduction
* ELTT2 is a single file-executable program
* intended for test, diagnosis and basic state changes of the Infineon
* Technologies TPM 2.0.\n
* \n
* @section Copyright
* Copyright (c) 2014 - 2017 Infineon Technologies AG ( www.infineon.com ).\n
* All rights reserved.\n
* \n
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:\n
* \n
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.\n
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.\n
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.\n
* \n
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <inttypes.h>
//-------------"Defines"-------------
#define TPM_RESP_MAX_SIZE 4096 ///< This is the maximum possible TPM response size in bytes.
#define TPM_REQ_MAX_SIZE 1024 ///< This is the maximum possible TPM request size in bytes. TBD: Find out correct value.
#define ERR_COMMUNICATION -1 ///< Return error check for read and write to the TPM.
#define ERR_BAD_CMD -2 ///< Error code for a bad command line argument or option.
#define TPM_SHA1_DIGEST_SIZE 20 ///< For all SHA-1 operations the digest's size is always 20 bytes.
#define TPM_SHA256_DIGEST_SIZE 32 ///< For all SHA-256 operations the digest's size is always 32 bytes.
#define TPM_SHA384_DIGEST_SIZE 48 ///< For all SHA-384 operations the digest's size is always 48 bytes.
#define TPM_CMD_HEADER_SIZE 10 ///< The size of a standard TPM command header is 10 bytes.
#define TPM_CMD_SIZE_OFFSET 2 ///< The offset of a TPM command's size value is 2 bytes.
#define HEX_BYTE_STRING_LENGTH 2 ///< A byte can be represented by two hexadecimal characters.
#ifndef INT_MAX
#define INT_MAX 0x7FFFFFF ///< The maximum value of a signed 32-bit integer.
#endif
// TPM Return codes
#define TPM_RC_SUCCESS 0x00000000 ///< The response error code for TPM_SUCCESS.
#define TPM_RC_BAD_TAG 0x0000001E ///< The response error code for TPM_RC_BAD_TAG.
#define TPM_RC_SIZE 0x00000095 ///< The response error code for TPM_RC_SIZE.
#define TPM_RC_INITIALIZE 0x00000100 ///< The response error code for TPM_RC_INITIALIZE.
#define TPM_RC_FAILURE 0x00000101 ///< The response error code for TPM_RC_FAILURE.
#define TPM_RC_LOCALITY 0x00000907 ///< The response error code for TPM_RC_LOCALITY.
#define FU_FIRMWARE_VALID_FLAG 4 ///< If this flag is set, the firmware is valid.
#define FU_OWNER_FLAG 1 ///< If this flag is set, the owner is set.
// print_response_buf options
#define PRINT_RESPONSE_CLEAR 1 ///< Prints response unformatted.
#define PRINT_RESPONSE_HEADERBLOCKS 2 ///< Prints response in commented blocks.
#define PRINT_RESPONSE_HEX_BLOCK 3 ///< Prints response in rows of 16 bytes and shows the line number.
#define PRINT_RESPONSE_HASH 4 ///< Prints response of Hash
#define PRINT_RESPONSE_WITHOUT_HEADER 12 ///< Prints the response buffer from byte 12.
#define PRINT_RESPONSE_HASH_WITHOUT_HEADER 16 ///< Prints the response buffer from byte 16.
#define PRINT_RESPONSE_WITH_HEADER 0 ///< Prints the response buffer from byte 0.
#define PRINT_RESPONSE_PCR_WITHOUT_HEADER 30 ///< Prints the pcr buffer from pcr_read.
// time conversion
#define YEAR_SECONDS 31536000 ///< Number of seconds in one year
#define DAY_SECONDS 86400 ///< Number of seconds in one day
#define HOUR_SECONDS 3600 ///< Number of seconds in one hour
#define MINUTE_SECONDS 60 ///< Number of seconds in one minute
#define MILISECOND_TO_SECOND 1000 ///< Convertion from miliseconds to seconds
// hash
#define STD_CC_HASH_SIZE 18 ///< Hash command size
// TPM_PT constants
#define PT_FIXED_SELECTOR 1 ///< Fixed GetCapability Flags
#define PT_VAR_SELECTOR 2 ///< Variable GetCapability Flags
//-------------"Macros"-------------
// Null pointer check
#define NULL_POINTER_CHECK(x) if (NULL == x) { ret_val = EINVAL; fprintf(stderr, "Error: Invalid argument.\n"); break; } ///< Argument NULL check.
#define MALLOC_ERROR_CHECK(x) if (NULL == x) { ret_val = errno; fprintf(stderr, "Error (re)allocating memory.\n"); break; } ///< Malloc error check.
#define MEMSET_FREE(x, y) if (NULL != x) { memset(x, 0, y); free(x); x = NULL; } ///< Sets memory to 0, frees memory and sets pointer to NULL.
// Return value check
#define RET_VAL_CHECK(x) if (EXIT_SUCCESS != x) { break; } ///< Return value check
// Command line option parser for hash algorithm
#define HASH_ALG_PARSER(o, c) \
do { \
if (o == option) \
{ \
if (c == argc) \
{ \
hash_algo = ALG_SHA1; \
} \
else \
{ \
if (0 == strcasecmp(optarg, "sha1")) \
{ \
hash_algo = ALG_SHA1; \
} \
else if (0 == strcasecmp(optarg, "sha256")) \
{ \
hash_algo = ALG_SHA256; \
} \
else if (0 == strcasecmp(optarg, "sha384")) \
{ \
hash_algo = ALG_SHA384; \
} \
else \
{ \
ret_val = ERR_BAD_CMD; \
fprintf(stderr, "Unknown option. Use '-h' for more information.\n"); \
break; \
} \
if (argc > optind) \
{ \
optarg = argv[optind++]; \
} \
} \
} \
else \
{ \
hash_algo = ALG_SHA256; \
} \
} while (0)
//--------------"Enums"--------------
// Hash algorithms
typedef enum hash_algo_enum
{
ALG_NULL,
ALG_SHA1,
ALG_SHA256,
ALG_SHA384,
} hash_algo_enum;
//-------------"Methods"-------------
/**
* @brief Convert (max.) 8 byte buffer to an unsigned 64-bit integer.
* @param [in] *input_buffer Input buffer. Make sure that its size is at least as high as offset + length.
* @param [in] offset Start byte for conversion.
* @param [in] length Amount of bytes to be converted.
* @param [out] *output_value Return the converted unsigned 64-bit integer.
* @param [in] input_buffer_size Size of input_buffer in bytes.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer or length is greater than 8.
* @retval EXIT_SUCCESS In case of success.
* @date 2014/06/26
*/
static int buf_to_uint64(uint8_t *input_buffer, uint32_t offset, uint32_t length, uint64_t *output_value, uint32_t input_buffer_size);
/**
* @brief Convert a hexadecimal string representation of bytes like "0A1F" and
returns an array containing the actual byte values as an array (e.g. { 0x0A, 0x1F }).
* @param [in] *byte_string Incoming bytes as string.
* @param [out] *byte_values Byte array representation of given input string.
* Must be allocated by caller with the length given in byte_values_size.
* @param [in] byte_values_size Size of byte_values array.
* @return One of the listed return codes.
* @retval EXIT_SUCCESS In case of success.
* @retval EINVAL In case of a NULL pointer.
* @retval value of errno In case parsing error.
* @date 2014/06/26
*/
static int hexstr_to_bytearray(char *byte_string, uint8_t *byte_values, size_t byte_values_size);
/**
* @brief Convert a number to a byte buffer.
* @param [in] input User input.
* @param [in] input_size Size of input data type in bytes.
* @param [out] *output_byte Return buffer for the converted integer.
Must be allocated by the caller with at least a size of 'input_size'.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @date 2014/06/26
*/
static int int_to_bytearray(uint64_t input, uint32_t input_size, uint8_t *output_byte);
/**
* @brief Create the PCR_Extend command.
* @param [in] *pcr_index_str User input string for PCR index.
* @param [in] *pcr_digest_str User input string of value to extend the selected PCR with.
* @param [out] *pcr_cmd_buf Return buffer for the complete command. Must be allocated by caller.
* @param [in] *pcr_cmd_buf_size Size of memory allocated at pcr_cmd_buf in bytes.
* @param [in] hash_algo Set to ALG_SHA1 for extending with SHA-1,
ALG_SHA256 for SHA-256, and ALG_SHA384 for SHA-384.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer or an invalid option.
* @retval EXIT_SUCCESS In case of success.
* @retval ERR_BAD_CMD In case of bad user input.
* @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray.
* @date 2014/06/26
*/
static int pcr_extend(char *pcr_index_str, char *pcr_digest_str, uint8_t *pcr_cmd_buf, size_t pcr_cmd_buf_size, hash_algo_enum hash_algo);
/**
* @brief Create the PCR_Allocate command.
* @param [out] *pcr_cmd_buf Return buffer for the complete command.
* @param [in] hash_algo Set to ALG_SHA1 to allocate SHA-1,
ALG_SHA256 for SHA-256, and ALG_SHA384 for SHA-384.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer or an invalid option.
* @retval EXIT_SUCCESS In case of success.
* @date 2022/05/09
*/
static int pcr_allocate(uint8_t *pcr_cmd_buf, hash_algo_enum hash_algo);
/**
* @brief Create the PCR_Read command.
* @param [in] *pcr_index_str User input string for PCR index.
* @param [out] *pcr_cmd_buf Return buffer for the complete command.
* @param [in] hash_algo Set to ALG_SHA1 for reading with SHA-1,
ALG_SHA256 for SHA-256, and ALG_SHA384 for SHA-384.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer or an invalid option.
* @retval EXIT_SUCCESS In case of success.
* @retval ERR_BAD_CMD In case of bad user input.
* @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray.
* @date 2014/06/26
*/
static int pcr_read(char *pcr_index_str, uint8_t *pcr_cmd_buf, hash_algo_enum hash_algo);
/**
* @brief Create the PCR_Reset command.
* @param [in] *pcr_index_str User input string for PCR index.
* @param [out] *pcr_cmd_buf Return buffer for the complete command.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @retval ERR_BAD_CMD In case of bad user input.
* @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray.
* @date 2014/06/26
*/
static int pcr_reset(char *pcr_index_str, uint8_t *pcr_cmd_buf);
/**
* @brief Print the command line usage and switches.
* @date 2014/06/26
*/
static void print_help();
/**
* @brief Print the response buffer in different formats.
* @param [in] *response_buf TPM response.
* @param [in] resp_size TPM response size.
* @param [in] offset Starting point for printing buffer.
* @param [in] format Select the output format.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer or an unknown output format has been transfered.
* @retval EXIT_SUCCESS In case of success.
* @retval buf_to_uint64 All error codes from buf_to_uint64.
* @date 2014/06/26
*/
static int print_response_buf(uint8_t *response_buf, size_t resp_size, uint32_t offset, int format);
/**
* @brief Print a TPM response.
* @param [in] *response_buf TPM response.
* @param [in] resp_size TPM response size.
* @param [in] option Defines appearance of output. Can have the following values:\n
- PRINT_RESPONSE_CLEAR
- PRINT_RESPONSE_HEADERBLOCKS
- PRINT_RESPONSE_HEX_BLOCK
- PRINT_RESPONSE_WITHOUT_HEADER
- PRINT_RESPONSE_WITH_HEADER
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @retval print_response_buf All error codes from print_response_buf.
* @retval print_clock_info All error codes from print_clock_info.
* @retval print_capability_flags All error codes from print_capability_flags.
* @date 2014/06/26
*/
static int response_print(uint8_t *response_buf, size_t resp_size, int option);
/**
* @brief Check a TPM response for errors.
* @param [in] *response_buf TPM response. Must have at least a size of TPM_CMD_HEADER_SIZE bytes.
* @return Returns the TPM return code extracted from the given TPM response or one of the listed return codes.
* @retval EINVAL In case of a NULL pointer.
* @retval buf_to_uint64 All error codes from buf_to_uint64.
* @retval EXIT_SUCCESS In case of success.
* @date 2014/06/26
*/
static int return_error_handling(uint8_t *response_buf);
/**
* @brief Transmit TPM command to /dev/tpm0 and get the response.
* @param [in] *buf TPM request.
* @param [in] length TPM request length.
* @param [out] *response TPM response.
* @param [out] *resp_length TPM response length.
* @return One of the listed return codes or the error code stored in the global errno system variable.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @date 2014/06/26
*/
static int tpmtool_transmit(const uint8_t *buf, ssize_t length, uint8_t *response, ssize_t *resp_length);
/**
* @brief Print the capability flags.
* @param [in] *response_buf TPM response.
* @param [in] cap_selector Type of capabilities to print.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @retval buf_to_uint64 All error codes from buf_to_uint64.
* @date 2014/06/26
*/
static int print_capability_flags(uint8_t *response_buf, uint8_t cap_selector);
/**
* @brief Print the clock info.
* @param [in] *response_buf TPM response.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @retval buf_to_uint64 All error codes from buf_to_uint64.
* @date 2014/06/26
*/
static int print_clock_info(uint8_t *response_buf);
/**
* @brief Create the get_random command.
* @param [in] *data_length_string User input string for random data length.
* @param [out] *response_buf Return buffer for the complete command.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @retval ERR_BAD_CMD In case of bad user input.
* @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray.
* @date 2014/06/26
*/
static int get_random(char *data_length_string, uint8_t *response_buf);
/**
* @brief Create the simple hash command.
* @param [in] *data_string User input string of data to be hashed.
* @param [in] hash_algo Set to ALG_SHA1 for hashing with SHA-1,
ALG_SHA256 for SHA-256, and ALG_SHA384 for SHA-384.
* @param [out] *hash_cmd_buf Return buffer for the complete command.
* @param [in] hash_cmd_buf_size Return buffer size.
* @return One of the listed return codes.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray.
* @retval int_to_bytearray All error codes from int_to_bytearray.
* @date 2014/06/26
*/
static int create_hash(char *data_string, hash_algo_enum hash_algo, uint8_t *hash_cmd_buf, uint32_t hash_cmd_buf_size);
/**
* @brief Create and transmit a sequence of TPM commands for hashing larger amounts of data.
* @param [in] *data_string User input string of data to be hashed.
* @param [in] hash_algo Set to ALG_SHA1 for hashing with SHA-1,
ALG_SHA256 for SHA-256, and ALG_SHA384 for SHA-384.
* @param [out] *tpm_response_buf TPM response.
* @param [out] *tpm_response_buf_size Size of tpm_response_buf.
* @return One of the listed return codes or the error code stored in the global errno system variable.
* @retval EINVAL In case of a NULL pointer.
* @retval EXIT_SUCCESS In case of success.
* @retval value of errno In case of memory allocation error.
* @retval buf_to_uint64 All error codes from buf_to_uint64.
* @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray.
* @retval int_to_bytearray All error codes from int_to_bytearray.
* @retval tpmtool_transmit All error codes from tpmtool_transmit.
* @retval print_response_buf All error codes from print_response_buf
* @date 2014/06/26
*/
static int create_hash_sequence(char *data_string, hash_algo_enum hash_algo, uint8_t *tpm_response_buf, ssize_t *tpm_response_buf_size);
//-------------"command bytes"-------------
static const uint8_t tpm2_startup_clear[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0C, // commandSize
0x00, 0x00, 0x01, 0x44, // TPM_CC_Startup
0x00, 0x00 // TPM_SU_CLEAR
};
static const uint8_t tpm2_startup_state[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0C, // commandSize
0x00, 0x00, 0x01, 0x44, // TPM_CC_Startup
0x00, 0x01 // TPM_SU_STATE
};
static const uint8_t tpm_cc_shutdown_clear[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0C, // commandSize
0x00, 0x00, 0x01, 0x45, // TPM_CC_Shutdown
0x00, 0x00 // TPM_SU_CLEAR
};
static const uint8_t tpm_cc_shutdown_state[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0C, // commandSize
0x00, 0x00, 0x01, 0x45, // TPM_CC_Shutdown
0x00, 0x01 // TPM_SU_STATE
};
static const uint8_t tpm2_self_test[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0B, // commandSize
0x00, 0x00, 0x01, 0x43, // TPM_CC_SelfTest
0x00 // fullTest=No
};
static const uint8_t tpm2_self_test_full[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0B, // commandSize
0x00, 0x00, 0x01, 0x43, // TPM_CC_SelfTest
0x01 // fullTest=Yes
};
static const uint8_t tpm_cc_get_test_result[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0A, // commandSize
0x00, 0x00, 0x01, 0x7C // TPM_CC_GetTestResult
};
static const uint8_t tpm2_self_test_incremental[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x2A, // commandSize
0x00, 0x00, 0x01, 0x42, // TPM_CC_IncrementalSelfTest
0x00, 0x00, 0x00, 0x0E, // Count of Algorithm
0x00, 0x01, 0x00, 0x04, // Algorithm two per line
0x00, 0x05, 0x00, 0x06,
0x00, 0x08, 0x00, 0x0A,
0x00, 0x0B, 0x00, 0x14,
0x00, 0x15, 0x00, 0x16,
0x00, 0x17, 0x00, 0x22,
0x00, 0x25, 0x00, 0x43
};
static const uint8_t tpm2_getrandom[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0C, // commandSize
0x00, 0x00, 0x01, 0x7B, // TPM_CC_GetRandom
0x00, 0x00 // bytesRequested (will be set later)
};
static const uint8_t tpm_cc_readclock[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0A, // commandSize
0x00, 0x00, 0x01, 0x81 // TPM_CC_ReadClock
};
static const uint8_t tpm2_getcapability_fixed[] ={
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x16, // commandSize
0x00, 0x00, 0x01, 0x7A, // TPM_CC_GetCapability
0x00, 0x00, 0x00, 0x06, // TPM_CAP_TPM_PROPERTIES (Property Type: TPM_PT)
0x00, 0x00, 0x01, 0x00, // Property: TPM_PT_FAMILY_INDICATOR: PT_GROUP * 1 + 0
0x00, 0x00, 0x00, 0x66 // PropertyCount 102 (from 100 - 201)
};
static const uint8_t tpm2_getcapability_var[] ={
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x16, // commandSize
0x00, 0x00, 0x01, 0x7A, // TPM_CC_GetCapability
0x00, 0x00, 0x00, 0x06, // TPM_CAP_TPM_PROPERTIES (Property Type: TPM_PT)
0x00, 0x00, 0x02, 0x00, // Property: TPM_PT_FAMILY_INDICATOR: PT_GROUP * 2 + 0
0x00, 0x00, 0x00, 0x02 // PropertyCount 02 (from 200 - 201)
};
// Hash
static const uint8_t tpm2_hash[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0e, // commandSize
0x00, 0x00, 0x01, 0x7D, // TPM_CC_Hash
0x00, 0x00, // size (will be set later)
// buffer (will be added later)
0x00, 0x00, // hashAlg (will be added later)
0x00, 0x00, 0x00, 0x00 // hierarchy of the ticket (TPM_RH_NULL; will be added later)
};
// HashSequence
static uint8_t tpm2_hash_sequence_start[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x0e, // commandSize
0x00, 0x00, 0x01, 0x86, // TPM_CC_HashSequenceStart
0x00, 0x00, // authSize (NULL Password)
// null (indicate a NULL Password)
0x00, 0x00 // hashAlg (will be set later)
};
static uint8_t tpm2_sequence_update[] = {
0x80, 0x02, // TPM_ST_SESSIONS
0x00, 0x00, 0x00, 0x00, // commandSize (will be set later)
0x00, 0x00, 0x01, 0x5c, // TPM_CC_SequenceUpdate
0x00, 0x00, 0x00, 0x00, // sequenceHandle (will be set later)
0x00, 0x00, // authSize (NULL Password)
// null (indicate a NULL Password)
0x00, 0x09, // authSize (password authorization session)
0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session)
0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00 // size (will be set later)
// buffer (will be added later)
};
static uint8_t tpm2_sequence_complete[] = {
0x80, 0x02, // TPM_ST_SESSIONS
0x00, 0x00, 0x00, 0x21, // commandSize
0x00, 0x00, 0x01, 0x3e, // TPM_CC_SequenceComplete
0x00, 0x00, 0x00, 0x00, // sequenceHandle (will be set later)
0x00, 0x00, // authSize (NULL Password)
// null (indicate a NULL Password)
0x00, 0x09, // authSize (password authorization session)
0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session)
0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, // size (NULL buffer)
// null (indicate an empty buffer buffer)
0x40, 0x00, 0x00, 0x07 // hierarchy of the ticket (TPM_RH_NULL)
};
static const uint8_t sha1_alg[] = {
0x00, 0x04 // command for sha1 alg
};
static const uint8_t sha256_alg[] = {
0x00, 0x0B // command for sha256 alg
};
static const uint8_t sha384_alg[] = {
0x00, 0x0C // command for sha384 alg
};
static const uint8_t tpm_cc_hash_hierarchy[] = {
0x40, 0x00, 0x00, 0x07 // hierarchy of the ticket (TPM_RH_NULL)
};
//PCR_Command
static const uint8_t tpm2_pcr_allocate[] = {
0x80, 0x02, // TPM_ST_SESSIONS
0x00, 0x00, 0x00, 0x31, // commandSize
0x00, 0x00, 0x01, 0x2B, // TPM_CC_PCR_Allocate
0x40, 0x00, 0x00, 0x0C, // TPM_RH_PLATFORM
0x00, 0x00, // authSize (NULL Password)
// null (indicate a NULL Password)
0x00, 0x09, // authSize (password authorization session)
0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session)
0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, // count (TPML_PCR_SELECTION)
0x00, 0x04, // hash (TPMS_PCR_SELECTION; SHA-1)
0x03, // sizeofSelect (TPMS_PCR_SELECTION)
0x00, 0x00, 0x00, // pcrSelect (TPMS_PCR_SELECTION; will be set later)
0x00, 0x0B, // hash (TPMS_PCR_SELECTION; SHA-256)
0x03, // sizeofSelect (TPMS_PCR_SELECTION)
0x00, 0x00, 0x00, // pcrSelect (TPMS_PCR_SELECTION; will be set later)
0x00, 0x0C, // hash (TPMS_PCR_SELECTION; SHA-384)
0x03, // sizeofSelect (TPMS_PCR_SELECTION)
0x00, 0x00, 0x00 // pcrSelect (TPMS_PCR_SELECTION; will be set later)
};
static const uint8_t tpm2_pcr_read[] = {
0x80, 0x01, // TPM_ST_NO_SESSIONS
0x00, 0x00, 0x00, 0x14, // commandSize
0x00, 0x00, 0x01, 0x7E, // TPM_CC_PCR_Read
0x00, 0x00, 0x00, 0x01, // count (TPML_PCR_SELECTION)
0x00, 0x00, // hash (TPMS_PCR_SELECTION; will be set later)
0x03, // sizeofSelect (TPMS_PCR_SELECTION)
0x00, 0x00, 0x00 // pcrSelect (TPMS_PCR_SELECTION)
};
static const uint8_t tpm2_pcr_extend[] = {
0x80, 0x02, // TPM_ST_SESSIONS
0x00, 0x00, 0x00, 0x00, // commandSize (will be set later)
0x00, 0x00, 0x01, 0x82, // TPM_CC_PCR_Extend
0x00, 0x00, 0x00, 0x00, // {PCR_FIRST:PCR_LAST} (TPMI_DH_PCR)
0x00, 0x00, // authSize (NULL Password)
// null (indicate a NULL Password)
0x00, 0x09, // authSize (password authorization session)
0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session)
0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, // count (TPML_DIGEST_VALUES)
0x00, 0x00 // hashAlg (TPMT_HA; will be set later)
// digest (TPMT_HA; will be added later)
};
static const uint8_t tpm2_pcr_reset[] = {
0x80, 0x02, // TPM_ST_SESSIONS
0x00, 0x00, 0x00, 0x1B, // commandSize
0x00, 0x00, 0x01, 0x3D, // TPM_CC_PCR_Reset
0x00, 0x00, 0x00, 0x00, // {PCR_FIRST:PCR_LAST} (TPMI_DH_PCR)
0x00, 0x00, // authSize (NULL Password)
// null (indicate a NULL Password)
0x00, 0x09, // authSize (password authorization session)
0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session)
0x00, 0x00, 0x01, 0x00, 0x00
};
#endif /* _ELTT2_H_ */

View File

@@ -1,29 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=hfcl
PKG_VERSION:=1.0
PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/hfcl
SECTION:=base
CATEGORY:=Utilities
TITLE:=hfcl
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
endef
define Build/Compile/Default
endef
Build/Compile = $(Build/Compile/Default)
define Package/hfcl/install
cp -rf ./files/* $(1)
endef
$(eval $(call BuildPackage,hfcl))

View File

@@ -1,43 +0,0 @@
#!/bin/sh
echo "Start Websocket check/recovery script"
ucentral_conn=$(netstat -atulpn | grep -i ucentral | awk '{print $6}')
hostname_AP=$(uci get system.@system[0].hostname)
uc_file_check=$(du /etc/config/ucentral | awk '{print $1}' )
sleep 20
curr_date=$(date)
if [[ "$uc_file_check" = 0 ]]
then
echo "[[$curr_date]] empty ucentral file found, need to factory reset"
ubi_mount=$(mount | grep ubifs | grep noatime | awk '{print $1}')
if [[ "$ubi_mount" != "/dev/ubi0_3" ]]
then
echo "[[$curr_date]] ubifs not mounted, need to reboot before factory reset, mount was $ubi_mount"
/sbin/reboot
else
/sbin/jffs2reset -y -r
fi
elif [[ "$hostname_AP" = "OpenWrt" ]]
then
echo "[[$curr_date]] hostname set to openwrt, doing ucentral and capabilities load"
/usr/share/ucentral/capabilities.uc
rlink=$(readlink -f /etc/ucentral/ucentral.active)
/usr/share/ucentral/ucentral.uc /etc/ucentral/ucentral.active
rm -rf /etc/ucentral/ucentral.active
ln -s $rlink /etc/ucentral/ucentral.active
sleep 60
ucentral_check=$(netstat -atulpn | grep -i ucentral | awk '{print $6}')
if [[ "$ucentral_check" != "ESTABLIHED" ]]
then
echo "[[$curr_date]] loading didn't work, need to factory reset"
/sbin/jffs2reset -y -r
fi
elif [[ "$ucentral_conn" != "ESTABLISHED" ]]
then
echo "[[$curr_date]] Ucentral either crashed or stopped, restarting the same"
/etc/init.d/ucentral restart
else
echo "[[$curr_date]] Ucentral working all fine, nothing to do"
fi

View File

@@ -1,18 +0,0 @@
#!/bin/sh
#rm -f /etc/rc.local
#cp -f /etc/loop.local /etc/rc.local
crontab -r
/etc/init.d/cron enable
/etc/init.d/cron start
sleep 60
crontab -l | { cat; echo "*/3 * * * * /bin/sh /etc/ucentral_check.sh >> /tmp/ucentral_check";} | crontab -
crontab -l | { cat; echo "* */4 * * * rm -rf /tmp/ucentral_check";} | crontab -
/etc/init.d/cron restart

View File

@@ -1,151 +0,0 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/version.mk
PKG_NAME:=ipq-wifi
PKG_RELEASE:=1
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
endef
define Build/Compile
endef
# Use ath10k-bdencoder from https://github.com/qca/qca-swiss-army-knife.git
# to generate the board-* files here.
#
# This is intended to be used on an interim basis until device-specific
# board data for new devices is available through the upstream compilation
#
# Please send a mail with your device-specific board files upstream.
# You can find instructions and examples on the linux-wireless wiki:
# <https://wireless.wiki.kernel.org/en/users/drivers/ath10k/boardfiles>
ALLWIFIBOARDS:= \
8dev_habanero-dvk \
aruba_ap-303 \
avm_fritzrepeater-1200 \
buffalo_wtr-m2133hp \
cellc_rtl30vw \
devolo_magic-2-wifi-next \
dlink_dap2610 \
edgecore_ecw5410 \
edgecore_ssw2ac2600 \
edgecore_oap100 \
engenius_eap2200 \
engenius_emd1 \
engenius_emr3500 \
ezviz_cs-w3-wd1200g-eup \
glinet_gl-ap1300 \
glinet_gl-s1300 \
linksys_ea8300 \
linksys_mr8300-v0 \
luma_wrtq-329acn \
mikrotik_hap-ac2 \
mikrotik_sxtsq-5-ac \
mobipromo_cm520-79f \
nec_wg2600hp3 \
plasmacloud_pa1200 \
plasmacloud_pa2200 \
qxwlan_e2600ac \
cig_wf610d \
wallys_dr40x9 \
tp-link_ec420-g1 \
udaya-a5-id2 \
hfcl_ion4
ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ipq-wifi-$(BOARD))
define Package/ipq-wifi-default
SUBMENU:=ath10k Board-Specific Overrides
SECTION:=firmware
CATEGORY:=Firmware
DEPENDS:=@(TARGET_ipq40xx||TARGET_ipq806x)
TITLE:=Custom Board
endef
define ipq-wifi-install-one-to
$(INSTALL_DIR) $(2)/lib/firmware/ath10k/$(3)/
$(INSTALL_DATA) $(1) $(2)/lib/firmware/ath10k/$(3)/board-2.bin
endef
define ipq-wifi-install-one
$(if $(filter $(suffix $(1)),.QCA4019 .qca4019),\
$(call ipq-wifi-install-one-to,$(1),$(2),QCA4019/hw1.0),\
$(if $(filter $(suffix $(1)),.QCA9888 .qca9888),\
$(call ipq-wifi-install-one-to,$(1),$(2),QCA9888/hw2.0),\
$(if $(filter $(suffix $(1)),.QCA9984 .qca9984),\
$(call ipq-wifi-install-one-to,$(1),$(2),QCA9984/hw1.0),\
$(error Unrecognized board-file suffix '$(suffix $(1))' for '$(1)')\
)))
endef
# Blank line required at end of above define due to foreach context
define generate-ipq-wifi-package
define Package/ipq-wifi-$(1)
$(call Package/ipq-wifi-default)
TITLE:=board-2.bin Overrides for $(2)
CONFLICTS:=$(PREV_BOARD)
endef
define Package/ipq-wifi-$(1)/description
The $(2) requires board-specific, reference ("cal") data
that is not yet present in the upstream wireless firmware distribution.
This package supplies board-2.bin file(s) that, in the interim,
overwrite those supplied by the ath10k-firmware-* packages.
This is package is only necessary for the $(2).
Do not install it for any other device!
endef
define Package/ipq-wifi-$(1)/install-overlay
$$$$(foreach IPQ_WIFI_BOARD_FILE,$$$$(wildcard board-$(1).*),\
$$$$(call ipq-wifi-install-one,$$$$(IPQ_WIFI_BOARD_FILE),$$(1)))
endef
PREV_BOARD+=ipq-wifi-$(1)
endef
# Add board name to ALLWIFIBOARDS
# Place files in this directory as board-<devicename>.<qca4019|qca9888|qca9984>
# Add $(eval $(call generate-ipq-wifi-package,<devicename>,<display name>))
$(eval $(call generate-ipq-wifi-package,8dev_habanero-dvk,8devices Habanero DVK))
$(eval $(call generate-ipq-wifi-package,aruba_ap-303,Aruba AP-303))
$(eval $(call generate-ipq-wifi-package,avm_fritzrepeater-1200,AVM FRITZRepeater 1200))
$(eval $(call generate-ipq-wifi-package,buffalo_wtr-m2133hp,Buffalo WTR-M2133HP))
$(eval $(call generate-ipq-wifi-package,cellc_rtl30vw, Cell C RTL30VW))
$(eval $(call generate-ipq-wifi-package,devolo_magic-2-wifi-next,devolo Magic 2 WiFi next))
$(eval $(call generate-ipq-wifi-package,dlink_dap2610,D-Link DAP-2610))
$(eval $(call generate-ipq-wifi-package,edgecore_ecw5410,Edgecore ECW5410))
$(eval $(call generate-ipq-wifi-package,edgecore_ssw2ac2600,Edgecore SSW2AC2600))
$(eval $(call generate-ipq-wifi-package,edgecore_oap100,Edgecore OAP100))
$(eval $(call generate-ipq-wifi-package,engenius_eap2200,EnGenius EAP2200))
$(eval $(call generate-ipq-wifi-package,engenius_emd1,EnGenius EMD1))
$(eval $(call generate-ipq-wifi-package,engenius_emr3500,EnGenius EMR3500))
$(eval $(call generate-ipq-wifi-package,ezviz_cs-w3-wd1200g-eup,EZVIZ CS-W3-WD1200G EUP))
$(eval $(call generate-ipq-wifi-package,glinet_gl-ap1300,GL.iNet GL-AP1300))
$(eval $(call generate-ipq-wifi-package,glinet_gl-s1300,GL.iNet GL-S1300))
$(eval $(call generate-ipq-wifi-package,linksys_ea8300,Linksys EA8300))
$(eval $(call generate-ipq-wifi-package,linksys_mr8300-v0,Linksys MR8300))
$(eval $(call generate-ipq-wifi-package,luma_wrtq-329acn,Luma WRTQ-329ACN))
$(eval $(call generate-ipq-wifi-package,mikrotik_hap-ac2,Mikrotik hAP ac2))
$(eval $(call generate-ipq-wifi-package,mikrotik_sxtsq-5-ac,MikroTik SXTsq 5 ac))
$(eval $(call generate-ipq-wifi-package,mobipromo_cm520-79f,MobiPromo CM520-79F))
$(eval $(call generate-ipq-wifi-package,nec_wg2600hp3,NEC Platforms WG2600HP3))
$(eval $(call generate-ipq-wifi-package,plasmacloud_pa1200,Plasma Cloud PA1200))
$(eval $(call generate-ipq-wifi-package,plasmacloud_pa2200,Plasma Cloud PA2200))
$(eval $(call generate-ipq-wifi-package,qxwlan_e2600ac,Qxwlan E2600AC))
$(eval $(call generate-ipq-wifi-package,cig_wf610d,CIG WF_610D))
$(eval $(call generate-ipq-wifi-package,tp-link_ec420-g1,tp-link EC420-G1))
$(eval $(call generate-ipq-wifi-package,wallys_dr40x9,Wallys DR40X9))
$(eval $(call generate-ipq-wifi-package,hfcl_ion4,HFCL ION4))
$(eval $(call generate-ipq-wifi-package,udaya-a5-id2,udaya A5 ID2))
$(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE))))

View File

@@ -1,31 +0,0 @@
include $(TOPDIR)/rules.mk
ARCH:=arm
BOARD:=ipq40xx
BOARDNAME:=Qualcomm Atheros IPQ40XX
FEATURES:=squashfs fpu ramdisk nand
CPU_TYPE:=cortex-a7
CPU_SUBTYPE:=neon-vfpv4
SUBTARGETS:=generic mikrotik
KERNEL_PATCHVER:=5.4
KERNEL_TESTING_PATCHVER:=5.4
DEVICE_TYPE:=qsdk
KERNELNAME:=zImage Image dtbs
GENERIC_BACKPORT_DIR := ${CURDIR}/backport-$(KERNEL_PATCHVER)
GENERIC_PATCH_DIR := ${CURDIR}/pending-$(KERNEL_PATCHVER)
GENERIC_HACK_DIR := ${CURDIR}/hack-$(KERNEL_PATCHVER)
GENERIC_FILES_DIR :=
GENERIC_LINUX_CONFIG:=${CURDIR}/config-$(KERNEL_PATCHVER)-ipq40xx
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += \
kmod-usb-dwc3-qcom \
kmod-leds-gpio kmod-gpio-button-hotplug swconfig \
kmod-ath10k-ct wpad-basic-wolfssl \
kmod-usb3 kmod-usb-dwc3 ath10k-firmware-qca4019-ct \
uboot-envtools
$(eval $(call BuildTarget))

View File

@@ -1,30 +0,0 @@
From 13b1ecc3401653a355798eb1dee10cc1608202f4 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 18 Jan 2016 12:27:49 +0100
Subject: [PATCH 33/34] Kbuild: don't hardcode path to awk in
scripts/ld-version.sh
On some systems /usr/bin/awk does not exist, or is broken. Find it via
$PATH instead.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
scripts/ld-version.sh | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/scripts/ld-version.sh
+++ b/scripts/ld-version.sh
@@ -1,6 +1,7 @@
-#!/usr/bin/awk -f
+#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# extract linker version number from stdin and turn into single number
+exec awk '
{
gsub(".*\\)", "");
gsub(".*version ", "");
@@ -9,3 +10,4 @@
print a[1]*100000000 + a[2]*1000000 + a[3]*10000;
exit
}
+'

View File

@@ -1,21 +0,0 @@
From 173019b66dcc9d68ad9333aa744dad1e369b5aa8 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sun, 9 Jul 2017 00:26:53 +0200
Subject: [PATCH 34/34] kernel: add compile fix for linux 4.9 on x86
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/Makefile
+++ b/Makefile
@@ -493,7 +493,7 @@ KBUILD_LDFLAGS :=
GCC_PLUGINS_CFLAGS :=
CLANG_FLAGS :=
-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
+export ARCH SRCARCH SUBARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE READELF PAHOLE LEX YACC AWK INSTALLKERNEL
export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ

View File

@@ -1,53 +0,0 @@
From afa0459daa7b08c7b2c879705b69d39b734a11d0 Mon Sep 17 00:00:00 2001
From: Masahiro Yamada <yamada.masahiro@socionext.com>
Date: Fri, 15 Nov 2019 02:42:21 +0900
Subject: [PATCH] modpost: add a helper to get data pointed by a symbol
When CONFIG_MODULE_REL_CRCS is enabled, the value of __crc_* is not
an absolute value, but the address to the CRC data embedded in the
.rodata section.
Getting the data pointed by the symbol value is somewhat complex.
Split it out into a new helper, sym_get_data().
I will reuse it to refactor namespace_from_kstrtabns() in the next
commit.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
scripts/mod/modpost.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -312,6 +312,18 @@ static const char *sec_name(struct elf_i
return sech_name(elf, &elf->sechdrs[secindex]);
}
+static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym)
+{
+ Elf_Shdr *sechdr = &info->sechdrs[sym->st_shndx];
+ unsigned long offset;
+
+ offset = sym->st_value;
+ if (info->hdr->e_type != ET_REL)
+ offset -= sechdr->sh_addr;
+
+ return (void *)info->hdr + sechdr->sh_offset + offset;
+}
+
#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
@@ -701,10 +713,7 @@ static void handle_modversions(struct mo
unsigned int *crcp;
/* symbol points to the CRC in the ELF object */
- crcp = (void *)info->hdr + sym->st_value +
- info->sechdrs[sym->st_shndx].sh_offset -
- (info->hdr->e_type != ET_REL ?
- info->sechdrs[sym->st_shndx].sh_addr : 0);
+ crcp = sym_get_data(info, sym);
crc = TO_NATIVE(*crcp);
}
sym_update_crc(symname + strlen("__crc_"), mod, crc,

View File

@@ -1,62 +0,0 @@
From e84f9fbbece1585f45a03ccc11eeabe121cadc1b Mon Sep 17 00:00:00 2001
From: Masahiro Yamada <yamada.masahiro@socionext.com>
Date: Fri, 15 Nov 2019 02:42:22 +0900
Subject: [PATCH] modpost: refactor namespace_from_kstrtabns() to not hard-code
section name
Currently, namespace_from_kstrtabns() relies on the fact that
namespace strings are recorded in the __ksymtab_strings section.
Actually, it is coded in include/linux/export.h, but modpost does
not need to hard-code the section name.
Elf_Sym::st_shndx holds the index of the relevant section. Using it is
a more portable way to get the namespace string.
Make namespace_from_kstrtabns() simply call sym_get_data(), and delete
the info->ksymtab_strings .
While I was here, I added more 'const' qualifiers to pointers.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
scripts/mod/modpost.c | 10 +++-------
scripts/mod/modpost.h | 1 -
2 files changed, 3 insertions(+), 8 deletions(-)
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -360,10 +360,10 @@ static enum export export_from_sec(struc
return export_unknown;
}
-static const char *namespace_from_kstrtabns(struct elf_info *info,
- Elf_Sym *kstrtabns)
+static const char *namespace_from_kstrtabns(const struct elf_info *info,
+ const Elf_Sym *sym)
{
- char *value = info->ksymtab_strings + kstrtabns->st_value;
+ const char *value = sym_get_data(info, sym);
return value[0] ? value : NULL;
}
@@ -605,10 +605,6 @@ static int parse_elf(struct elf_info *in
info->export_unused_gpl_sec = i;
else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
info->export_gpl_future_sec = i;
- else if (strcmp(secname, "__ksymtab_strings") == 0)
- info->ksymtab_strings = (void *)hdr +
- sechdrs[i].sh_offset -
- sechdrs[i].sh_addr;
if (sechdrs[i].sh_type == SHT_SYMTAB) {
unsigned int sh_link_idx;
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -143,7 +143,6 @@ struct elf_info {
Elf_Section export_gpl_sec;
Elf_Section export_unused_gpl_sec;
Elf_Section export_gpl_future_sec;
- char *ksymtab_strings;
char *strtab;
char *modinfo;
unsigned int modinfo_len;

View File

@@ -1,176 +0,0 @@
From: Robin Murphy <robin.murphy@arm.com>
Date: Wed, 15 Jan 2020 16:42:39 +0000
Subject: [PATCH] arm64: Implement optimised checksum routine
Apparently there exist certain workloads which rely heavily on software
checksumming, for which the generic do_csum() implementation becomes a
significant bottleneck. Therefore let's give arm64 its own optimised
version - for ease of maintenance this foregoes assembly or intrisics,
and is thus not actually arm64-specific, but does rely heavily on C
idioms that translate well to the A64 ISA and the typical load/store
capabilities of most ARMv8 CPU cores.
The resulting increase in checksum throughput scales nicely with buffer
size, tending towards 4x for a small in-order core (Cortex-A53), and up
to 6x or more for an aggressive big core (Ampere eMAG).
Reported-by: Lingyan Huang <huanglingyan2@huawei.com>
Tested-by: Lingyan Huang <huanglingyan2@huawei.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
create mode 100644 arch/arm64/lib/csum.c
--- a/arch/arm64/include/asm/checksum.h
+++ b/arch/arm64/include/asm/checksum.h
@@ -36,6 +36,9 @@ static inline __sum16 ip_fast_csum(const
}
#define ip_fast_csum ip_fast_csum
+extern unsigned int do_csum(const unsigned char *buff, int len);
+#define do_csum do_csum
+
#include <asm-generic/checksum.h>
#endif /* __ASM_CHECKSUM_H */
--- a/arch/arm64/lib/Makefile
+++ b/arch/arm64/lib/Makefile
@@ -1,9 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
lib-y := clear_user.o delay.o copy_from_user.o \
copy_to_user.o copy_in_user.o copy_page.o \
- clear_page.o memchr.o memcpy.o memmove.o memset.o \
- memcmp.o strcmp.o strncmp.o strlen.o strnlen.o \
- strchr.o strrchr.o tishift.o
+ clear_page.o csum.o memchr.o memcpy.o memmove.o \
+ memset.o memcmp.o strcmp.o strncmp.o strlen.o \
+ strnlen.o strchr.o strrchr.o tishift.o
ifeq ($(CONFIG_KERNEL_MODE_NEON), y)
obj-$(CONFIG_XOR_BLOCKS) += xor-neon.o
--- /dev/null
+++ b/arch/arm64/lib/csum.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2019-2020 Arm Ltd.
+
+#include <linux/compiler.h>
+#include <linux/kasan-checks.h>
+#include <linux/kernel.h>
+
+#include <net/checksum.h>
+
+/* Looks dumb, but generates nice-ish code */
+static u64 accumulate(u64 sum, u64 data)
+{
+ __uint128_t tmp = (__uint128_t)sum + data;
+ return tmp + (tmp >> 64);
+}
+
+unsigned int do_csum(const unsigned char *buff, int len)
+{
+ unsigned int offset, shift, sum;
+ const u64 *ptr;
+ u64 data, sum64 = 0;
+
+ offset = (unsigned long)buff & 7;
+ /*
+ * This is to all intents and purposes safe, since rounding down cannot
+ * result in a different page or cache line being accessed, and @buff
+ * should absolutely not be pointing to anything read-sensitive. We do,
+ * however, have to be careful not to piss off KASAN, which means using
+ * unchecked reads to accommodate the head and tail, for which we'll
+ * compensate with an explicit check up-front.
+ */
+ kasan_check_read(buff, len);
+ ptr = (u64 *)(buff - offset);
+ len = len + offset - 8;
+
+ /*
+ * Head: zero out any excess leading bytes. Shifting back by the same
+ * amount should be at least as fast as any other way of handling the
+ * odd/even alignment, and means we can ignore it until the very end.
+ */
+ shift = offset * 8;
+ data = READ_ONCE_NOCHECK(*ptr++);
+#ifdef __LITTLE_ENDIAN
+ data = (data >> shift) << shift;
+#else
+ data = (data << shift) >> shift;
+#endif
+
+ /*
+ * Body: straightforward aligned loads from here on (the paired loads
+ * underlying the quadword type still only need dword alignment). The
+ * main loop strictly excludes the tail, so the second loop will always
+ * run at least once.
+ */
+ while (unlikely(len > 64)) {
+ __uint128_t tmp1, tmp2, tmp3, tmp4;
+
+ tmp1 = READ_ONCE_NOCHECK(*(__uint128_t *)ptr);
+ tmp2 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 2));
+ tmp3 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 4));
+ tmp4 = READ_ONCE_NOCHECK(*(__uint128_t *)(ptr + 6));
+
+ len -= 64;
+ ptr += 8;
+
+ /* This is the "don't dump the carry flag into a GPR" idiom */
+ tmp1 += (tmp1 >> 64) | (tmp1 << 64);
+ tmp2 += (tmp2 >> 64) | (tmp2 << 64);
+ tmp3 += (tmp3 >> 64) | (tmp3 << 64);
+ tmp4 += (tmp4 >> 64) | (tmp4 << 64);
+ tmp1 = ((tmp1 >> 64) << 64) | (tmp2 >> 64);
+ tmp1 += (tmp1 >> 64) | (tmp1 << 64);
+ tmp3 = ((tmp3 >> 64) << 64) | (tmp4 >> 64);
+ tmp3 += (tmp3 >> 64) | (tmp3 << 64);
+ tmp1 = ((tmp1 >> 64) << 64) | (tmp3 >> 64);
+ tmp1 += (tmp1 >> 64) | (tmp1 << 64);
+ tmp1 = ((tmp1 >> 64) << 64) | sum64;
+ tmp1 += (tmp1 >> 64) | (tmp1 << 64);
+ sum64 = tmp1 >> 64;
+ }
+ while (len > 8) {
+ __uint128_t tmp;
+
+ sum64 = accumulate(sum64, data);
+ tmp = READ_ONCE_NOCHECK(*(__uint128_t *)ptr);
+
+ len -= 16;
+ ptr += 2;
+
+#ifdef __LITTLE_ENDIAN
+ data = tmp >> 64;
+ sum64 = accumulate(sum64, tmp);
+#else
+ data = tmp;
+ sum64 = accumulate(sum64, tmp >> 64);
+#endif
+ }
+ if (len > 0) {
+ sum64 = accumulate(sum64, data);
+ data = READ_ONCE_NOCHECK(*ptr);
+ len -= 8;
+ }
+ /*
+ * Tail: zero any over-read bytes similarly to the head, again
+ * preserving odd/even alignment.
+ */
+ shift = len * -8;
+#ifdef __LITTLE_ENDIAN
+ data = (data << shift) >> shift;
+#else
+ data = (data >> shift) << shift;
+#endif
+ sum64 = accumulate(sum64, data);
+
+ /* Finally, folding */
+ sum64 += (sum64 >> 32) | (sum64 << 32);
+ sum = sum64 >> 32;
+ sum += (sum >> 16) | (sum << 16);
+ if (offset & 1)
+ return (u16)swab32(sum);
+
+ return sum >> 16;
+}

View File

@@ -1,28 +0,0 @@
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 17 Jan 2020 15:48:39 +0000
Subject: [PATCH] arm64: csum: Fix pathological zero-length calls
In validating the checksumming results of the new routine, I sadly
neglected to test its not-checksumming results. Thus it slipped through
that the one case where @buff is already dword-aligned and @len = 0
manages to defeat the tail-masking logic and behave as if @len = 8.
For a zero length it doesn't make much sense to deference @buff anyway,
so just add an early return (which has essentially zero impact on
performance).
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
--- a/arch/arm64/lib/csum.c
+++ b/arch/arm64/lib/csum.c
@@ -20,6 +20,9 @@ unsigned int do_csum(const unsigned char
const u64 *ptr;
u64 data, sum64 = 0;
+ if (unlikely(len == 0))
+ return 0;
+
offset = (unsigned long)buff & 7;
/*
* This is to all intents and purposes safe, since rounding down cannot

View File

@@ -1,112 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:07 +0100
Subject: [PATCH] crypto: lib - tidy up lib/crypto Kconfig and Makefile
commit 746b2e024c67aa605ac12d135cd7085a49cf9dc4 upstream.
In preparation of introducing a set of crypto library interfaces, tidy
up the Makefile and split off the Kconfig symbols into a separate file.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
crypto/Kconfig | 13 +------------
lib/crypto/Kconfig | 15 +++++++++++++++
lib/crypto/Makefile | 16 ++++++++--------
3 files changed, 24 insertions(+), 20 deletions(-)
create mode 100644 lib/crypto/Kconfig
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -878,9 +878,6 @@ config CRYPTO_SHA1_PPC_SPE
SHA-1 secure hash standard (DFIPS 180-4) implemented
using powerpc SPE SIMD instruction set.
-config CRYPTO_LIB_SHA256
- tristate
-
config CRYPTO_SHA256
tristate "SHA224 and SHA256 digest algorithm"
select CRYPTO_HASH
@@ -1019,9 +1016,6 @@ config CRYPTO_GHASH_CLMUL_NI_INTEL
comment "Ciphers"
-config CRYPTO_LIB_AES
- tristate
-
config CRYPTO_AES
tristate "AES cipher algorithms"
select CRYPTO_ALGAPI
@@ -1150,9 +1144,6 @@ config CRYPTO_ANUBIS
<https://www.cosic.esat.kuleuven.be/nessie/reports/>
<http://www.larc.usp.br/~pbarreto/AnubisPage.html>
-config CRYPTO_LIB_ARC4
- tristate
-
config CRYPTO_ARC4
tristate "ARC4 cipher algorithm"
select CRYPTO_BLKCIPHER
@@ -1339,9 +1330,6 @@ config CRYPTO_CAST6_AVX_X86_64
This module provides the Cast6 cipher algorithm that processes
eight blocks parallel using the AVX instruction set.
-config CRYPTO_LIB_DES
- tristate
-
config CRYPTO_DES
tristate "DES and Triple DES EDE cipher algorithms"
select CRYPTO_ALGAPI
@@ -1845,6 +1833,7 @@ config CRYPTO_STATS
config CRYPTO_HASH_INFO
bool
+source "lib/crypto/Kconfig"
source "drivers/crypto/Kconfig"
source "crypto/asymmetric_keys/Kconfig"
source "certs/Kconfig"
--- /dev/null
+++ b/lib/crypto/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+
+comment "Crypto library routines"
+
+config CRYPTO_LIB_AES
+ tristate
+
+config CRYPTO_LIB_ARC4
+ tristate
+
+config CRYPTO_LIB_DES
+ tristate
+
+config CRYPTO_LIB_SHA256
+ tristate
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -1,13 +1,13 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_CRYPTO_LIB_AES) += libaes.o
-libaes-y := aes.o
+obj-$(CONFIG_CRYPTO_LIB_AES) += libaes.o
+libaes-y := aes.o
-obj-$(CONFIG_CRYPTO_LIB_ARC4) += libarc4.o
-libarc4-y := arc4.o
+obj-$(CONFIG_CRYPTO_LIB_ARC4) += libarc4.o
+libarc4-y := arc4.o
-obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o
-libdes-y := des.o
+obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o
+libdes-y := des.o
-obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o
-libsha256-y := sha256.o
+obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o
+libsha256-y := sha256.o

View File

@@ -1,668 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:08 +0100
Subject: [PATCH] crypto: chacha - move existing library code into lib/crypto
commit 5fb8ef25803ef33e2eb60b626435828b937bed75 upstream.
Currently, our generic ChaCha implementation consists of a permute
function in lib/chacha.c that operates on the 64-byte ChaCha state
directly [and which is always included into the core kernel since it
is used by the /dev/random driver], and the crypto API plumbing to
expose it as a skcipher.
In order to support in-kernel users that need the ChaCha streamcipher
but have no need [or tolerance] for going through the abstractions of
the crypto API, let's expose the streamcipher bits via a library API
as well, in a way that permits the implementation to be superseded by
an architecture specific one if provided.
So move the streamcipher code into a separate module in lib/crypto,
and expose the init() and crypt() routines to users of the library.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/arm/crypto/chacha-neon-glue.c | 2 +-
arch/arm64/crypto/chacha-neon-glue.c | 2 +-
arch/x86/crypto/chacha_glue.c | 2 +-
crypto/Kconfig | 1 +
crypto/chacha_generic.c | 60 ++--------------------
include/crypto/chacha.h | 77 ++++++++++++++++++++++------
include/crypto/internal/chacha.h | 53 +++++++++++++++++++
lib/Makefile | 3 +-
lib/crypto/Kconfig | 26 ++++++++++
lib/crypto/Makefile | 4 ++
lib/{ => crypto}/chacha.c | 20 ++++----
lib/crypto/libchacha.c | 35 +++++++++++++
12 files changed, 199 insertions(+), 86 deletions(-)
create mode 100644 include/crypto/internal/chacha.h
rename lib/{ => crypto}/chacha.c (88%)
create mode 100644 lib/crypto/libchacha.c
--- a/arch/arm/crypto/chacha-neon-glue.c
+++ b/arch/arm/crypto/chacha-neon-glue.c
@@ -20,7 +20,7 @@
*/
#include <crypto/algapi.h>
-#include <crypto/chacha.h>
+#include <crypto/internal/chacha.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
#include <linux/kernel.h>
--- a/arch/arm64/crypto/chacha-neon-glue.c
+++ b/arch/arm64/crypto/chacha-neon-glue.c
@@ -20,7 +20,7 @@
*/
#include <crypto/algapi.h>
-#include <crypto/chacha.h>
+#include <crypto/internal/chacha.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
#include <linux/kernel.h>
--- a/arch/x86/crypto/chacha_glue.c
+++ b/arch/x86/crypto/chacha_glue.c
@@ -7,7 +7,7 @@
*/
#include <crypto/algapi.h>
-#include <crypto/chacha.h>
+#include <crypto/internal/chacha.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
#include <linux/kernel.h>
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1393,6 +1393,7 @@ config CRYPTO_SALSA20
config CRYPTO_CHACHA20
tristate "ChaCha stream cipher algorithms"
+ select CRYPTO_LIB_CHACHA_GENERIC
select CRYPTO_BLKCIPHER
help
The ChaCha20, XChaCha20, and XChaCha12 stream cipher algorithms.
--- a/crypto/chacha_generic.c
+++ b/crypto/chacha_generic.c
@@ -8,29 +8,10 @@
#include <asm/unaligned.h>
#include <crypto/algapi.h>
-#include <crypto/chacha.h>
+#include <crypto/internal/chacha.h>
#include <crypto/internal/skcipher.h>
#include <linux/module.h>
-static void chacha_docrypt(u32 *state, u8 *dst, const u8 *src,
- unsigned int bytes, int nrounds)
-{
- /* aligned to potentially speed up crypto_xor() */
- u8 stream[CHACHA_BLOCK_SIZE] __aligned(sizeof(long));
-
- while (bytes >= CHACHA_BLOCK_SIZE) {
- chacha_block(state, stream, nrounds);
- crypto_xor_cpy(dst, src, stream, CHACHA_BLOCK_SIZE);
- bytes -= CHACHA_BLOCK_SIZE;
- dst += CHACHA_BLOCK_SIZE;
- src += CHACHA_BLOCK_SIZE;
- }
- if (bytes) {
- chacha_block(state, stream, nrounds);
- crypto_xor_cpy(dst, src, stream, bytes);
- }
-}
-
static int chacha_stream_xor(struct skcipher_request *req,
const struct chacha_ctx *ctx, const u8 *iv)
{
@@ -48,8 +29,8 @@ static int chacha_stream_xor(struct skci
if (nbytes < walk.total)
nbytes = round_down(nbytes, CHACHA_BLOCK_SIZE);
- chacha_docrypt(state, walk.dst.virt.addr, walk.src.virt.addr,
- nbytes, ctx->nrounds);
+ chacha_crypt_generic(state, walk.dst.virt.addr,
+ walk.src.virt.addr, nbytes, ctx->nrounds);
err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
}
@@ -58,41 +39,10 @@ static int chacha_stream_xor(struct skci
void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv)
{
- state[0] = 0x61707865; /* "expa" */
- state[1] = 0x3320646e; /* "nd 3" */
- state[2] = 0x79622d32; /* "2-by" */
- state[3] = 0x6b206574; /* "te k" */
- state[4] = ctx->key[0];
- state[5] = ctx->key[1];
- state[6] = ctx->key[2];
- state[7] = ctx->key[3];
- state[8] = ctx->key[4];
- state[9] = ctx->key[5];
- state[10] = ctx->key[6];
- state[11] = ctx->key[7];
- state[12] = get_unaligned_le32(iv + 0);
- state[13] = get_unaligned_le32(iv + 4);
- state[14] = get_unaligned_le32(iv + 8);
- state[15] = get_unaligned_le32(iv + 12);
+ chacha_init_generic(state, ctx->key, iv);
}
EXPORT_SYMBOL_GPL(crypto_chacha_init);
-static int chacha_setkey(struct crypto_skcipher *tfm, const u8 *key,
- unsigned int keysize, int nrounds)
-{
- struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
- int i;
-
- if (keysize != CHACHA_KEY_SIZE)
- return -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(ctx->key); i++)
- ctx->key[i] = get_unaligned_le32(key + i * sizeof(u32));
-
- ctx->nrounds = nrounds;
- return 0;
-}
-
int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
unsigned int keysize)
{
@@ -126,7 +76,7 @@ int crypto_xchacha_crypt(struct skcipher
/* Compute the subkey given the original key and first 128 nonce bits */
crypto_chacha_init(state, ctx, req->iv);
- hchacha_block(state, subctx.key, ctx->nrounds);
+ hchacha_block_generic(state, subctx.key, ctx->nrounds);
subctx.nrounds = ctx->nrounds;
/* Build the real IV */
--- a/include/crypto/chacha.h
+++ b/include/crypto/chacha.h
@@ -15,9 +15,8 @@
#ifndef _CRYPTO_CHACHA_H
#define _CRYPTO_CHACHA_H
-#include <crypto/skcipher.h>
+#include <asm/unaligned.h>
#include <linux/types.h>
-#include <linux/crypto.h>
/* 32-bit stream position, then 96-bit nonce (RFC7539 convention) */
#define CHACHA_IV_SIZE 16
@@ -29,26 +28,70 @@
/* 192-bit nonce, then 64-bit stream position */
#define XCHACHA_IV_SIZE 32
-struct chacha_ctx {
- u32 key[8];
- int nrounds;
-};
-
-void chacha_block(u32 *state, u8 *stream, int nrounds);
+void chacha_block_generic(u32 *state, u8 *stream, int nrounds);
static inline void chacha20_block(u32 *state, u8 *stream)
{
- chacha_block(state, stream, 20);
+ chacha_block_generic(state, stream, 20);
}
-void hchacha_block(const u32 *in, u32 *out, int nrounds);
-void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv);
+void hchacha_block_arch(const u32 *state, u32 *out, int nrounds);
+void hchacha_block_generic(const u32 *state, u32 *out, int nrounds);
+
+static inline void hchacha_block(const u32 *state, u32 *out, int nrounds)
+{
+ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA))
+ hchacha_block_arch(state, out, nrounds);
+ else
+ hchacha_block_generic(state, out, nrounds);
+}
-int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
- unsigned int keysize);
-int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
- unsigned int keysize);
+void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv);
+static inline void chacha_init_generic(u32 *state, const u32 *key, const u8 *iv)
+{
+ state[0] = 0x61707865; /* "expa" */
+ state[1] = 0x3320646e; /* "nd 3" */
+ state[2] = 0x79622d32; /* "2-by" */
+ state[3] = 0x6b206574; /* "te k" */
+ state[4] = key[0];
+ state[5] = key[1];
+ state[6] = key[2];
+ state[7] = key[3];
+ state[8] = key[4];
+ state[9] = key[5];
+ state[10] = key[6];
+ state[11] = key[7];
+ state[12] = get_unaligned_le32(iv + 0);
+ state[13] = get_unaligned_le32(iv + 4);
+ state[14] = get_unaligned_le32(iv + 8);
+ state[15] = get_unaligned_le32(iv + 12);
+}
-int crypto_chacha_crypt(struct skcipher_request *req);
-int crypto_xchacha_crypt(struct skcipher_request *req);
+static inline void chacha_init(u32 *state, const u32 *key, const u8 *iv)
+{
+ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA))
+ chacha_init_arch(state, key, iv);
+ else
+ chacha_init_generic(state, key, iv);
+}
+
+void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes, int nrounds);
+void chacha_crypt_generic(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes, int nrounds);
+
+static inline void chacha_crypt(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes, int nrounds)
+{
+ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA))
+ chacha_crypt_arch(state, dst, src, bytes, nrounds);
+ else
+ chacha_crypt_generic(state, dst, src, bytes, nrounds);
+}
+
+static inline void chacha20_crypt(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes)
+{
+ chacha_crypt(state, dst, src, bytes, 20);
+}
#endif /* _CRYPTO_CHACHA_H */
--- /dev/null
+++ b/include/crypto/internal/chacha.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _CRYPTO_INTERNAL_CHACHA_H
+#define _CRYPTO_INTERNAL_CHACHA_H
+
+#include <crypto/chacha.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/crypto.h>
+
+struct chacha_ctx {
+ u32 key[8];
+ int nrounds;
+};
+
+void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv);
+
+static inline int chacha_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ unsigned int keysize, int nrounds)
+{
+ struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
+ int i;
+
+ if (keysize != CHACHA_KEY_SIZE)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->key); i++)
+ ctx->key[i] = get_unaligned_le32(key + i * sizeof(u32));
+
+ ctx->nrounds = nrounds;
+ return 0;
+}
+
+static inline int chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ unsigned int keysize)
+{
+ return chacha_setkey(tfm, key, keysize, 20);
+}
+
+static int inline chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ unsigned int keysize)
+{
+ return chacha_setkey(tfm, key, keysize, 12);
+}
+
+int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ unsigned int keysize);
+int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ unsigned int keysize);
+
+int crypto_chacha_crypt(struct skcipher_request *req);
+int crypto_xchacha_crypt(struct skcipher_request *req);
+
+#endif /* _CRYPTO_CHACHA_H */
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -26,8 +26,7 @@ endif
lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o timerqueue.o xarray.o \
- idr.o extable.o \
- sha1.o chacha.o irq_regs.o argv_split.o \
+ idr.o extable.o sha1.o irq_regs.o argv_split.o \
flex_proportions.o ratelimit.o show_mem.o \
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -8,6 +8,32 @@ config CRYPTO_LIB_AES
config CRYPTO_LIB_ARC4
tristate
+config CRYPTO_ARCH_HAVE_LIB_CHACHA
+ tristate
+ help
+ Declares whether the architecture provides an arch-specific
+ accelerated implementation of the ChaCha library interface,
+ either builtin or as a module.
+
+config CRYPTO_LIB_CHACHA_GENERIC
+ tristate
+ select CRYPTO_ALGAPI
+ help
+ This symbol can be depended upon by arch implementations of the
+ ChaCha library interface that require the generic code as a
+ fallback, e.g., for SIMD implementations. If no arch specific
+ implementation is enabled, this implementation serves the users
+ of CRYPTO_LIB_CHACHA.
+
+config CRYPTO_LIB_CHACHA
+ tristate "ChaCha library interface"
+ depends on CRYPTO_ARCH_HAVE_LIB_CHACHA || !CRYPTO_ARCH_HAVE_LIB_CHACHA
+ select CRYPTO_LIB_CHACHA_GENERIC if CRYPTO_ARCH_HAVE_LIB_CHACHA=n
+ help
+ Enable the ChaCha library interface. This interface may be fulfilled
+ by either the generic implementation or an arch-specific one, if one
+ is available and enabled.
+
config CRYPTO_LIB_DES
tristate
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -1,5 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
+# chacha is used by the /dev/random driver which is always builtin
+obj-y += chacha.o
+obj-$(CONFIG_CRYPTO_LIB_CHACHA_GENERIC) += libchacha.o
+
obj-$(CONFIG_CRYPTO_LIB_AES) += libaes.o
libaes-y := aes.o
--- a/lib/chacha.c
+++ /dev/null
@@ -1,113 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * The "hash function" used as the core of the ChaCha stream cipher (RFC7539)
- *
- * Copyright (C) 2015 Martin Willi
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/bitops.h>
-#include <linux/cryptohash.h>
-#include <asm/unaligned.h>
-#include <crypto/chacha.h>
-
-static void chacha_permute(u32 *x, int nrounds)
-{
- int i;
-
- /* whitelist the allowed round counts */
- WARN_ON_ONCE(nrounds != 20 && nrounds != 12);
-
- for (i = 0; i < nrounds; i += 2) {
- x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 16);
- x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 16);
- x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 16);
- x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 16);
-
- x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 12);
- x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 12);
- x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 12);
- x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 12);
-
- x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 8);
- x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 8);
- x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 8);
- x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 8);
-
- x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 7);
- x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 7);
- x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 7);
- x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 7);
-
- x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 16);
- x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 16);
- x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 16);
- x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 16);
-
- x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 12);
- x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 12);
- x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 12);
- x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 12);
-
- x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 8);
- x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 8);
- x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 8);
- x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 8);
-
- x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 7);
- x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 7);
- x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 7);
- x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 7);
- }
-}
-
-/**
- * chacha_block - generate one keystream block and increment block counter
- * @state: input state matrix (16 32-bit words)
- * @stream: output keystream block (64 bytes)
- * @nrounds: number of rounds (20 or 12; 20 is recommended)
- *
- * This is the ChaCha core, a function from 64-byte strings to 64-byte strings.
- * The caller has already converted the endianness of the input. This function
- * also handles incrementing the block counter in the input matrix.
- */
-void chacha_block(u32 *state, u8 *stream, int nrounds)
-{
- u32 x[16];
- int i;
-
- memcpy(x, state, 64);
-
- chacha_permute(x, nrounds);
-
- for (i = 0; i < ARRAY_SIZE(x); i++)
- put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]);
-
- state[12]++;
-}
-EXPORT_SYMBOL(chacha_block);
-
-/**
- * hchacha_block - abbreviated ChaCha core, for XChaCha
- * @in: input state matrix (16 32-bit words)
- * @out: output (8 32-bit words)
- * @nrounds: number of rounds (20 or 12; 20 is recommended)
- *
- * HChaCha is the ChaCha equivalent of HSalsa and is an intermediate step
- * towards XChaCha (see https://cr.yp.to/snuffle/xsalsa-20081128.pdf). HChaCha
- * skips the final addition of the initial state, and outputs only certain words
- * of the state. It should not be used for streaming directly.
- */
-void hchacha_block(const u32 *in, u32 *out, int nrounds)
-{
- u32 x[16];
-
- memcpy(x, in, 64);
-
- chacha_permute(x, nrounds);
-
- memcpy(&out[0], &x[0], 16);
- memcpy(&out[4], &x[12], 16);
-}
-EXPORT_SYMBOL(hchacha_block);
--- /dev/null
+++ b/lib/crypto/chacha.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * The "hash function" used as the core of the ChaCha stream cipher (RFC7539)
+ *
+ * Copyright (C) 2015 Martin Willi
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/cryptohash.h>
+#include <asm/unaligned.h>
+#include <crypto/chacha.h>
+
+static void chacha_permute(u32 *x, int nrounds)
+{
+ int i;
+
+ /* whitelist the allowed round counts */
+ WARN_ON_ONCE(nrounds != 20 && nrounds != 12);
+
+ for (i = 0; i < nrounds; i += 2) {
+ x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 16);
+ x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 16);
+ x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 16);
+ x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 16);
+
+ x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 12);
+ x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 12);
+ x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 12);
+ x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 12);
+
+ x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 8);
+ x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 8);
+ x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 8);
+ x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 8);
+
+ x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 7);
+ x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 7);
+ x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 7);
+ x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 7);
+
+ x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 16);
+ x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 16);
+ x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 16);
+ x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 16);
+
+ x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 12);
+ x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 12);
+ x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 12);
+ x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 12);
+
+ x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 8);
+ x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 8);
+ x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 8);
+ x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 8);
+
+ x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 7);
+ x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 7);
+ x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 7);
+ x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 7);
+ }
+}
+
+/**
+ * chacha_block - generate one keystream block and increment block counter
+ * @state: input state matrix (16 32-bit words)
+ * @stream: output keystream block (64 bytes)
+ * @nrounds: number of rounds (20 or 12; 20 is recommended)
+ *
+ * This is the ChaCha core, a function from 64-byte strings to 64-byte strings.
+ * The caller has already converted the endianness of the input. This function
+ * also handles incrementing the block counter in the input matrix.
+ */
+void chacha_block_generic(u32 *state, u8 *stream, int nrounds)
+{
+ u32 x[16];
+ int i;
+
+ memcpy(x, state, 64);
+
+ chacha_permute(x, nrounds);
+
+ for (i = 0; i < ARRAY_SIZE(x); i++)
+ put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]);
+
+ state[12]++;
+}
+EXPORT_SYMBOL(chacha_block_generic);
+
+/**
+ * hchacha_block_generic - abbreviated ChaCha core, for XChaCha
+ * @state: input state matrix (16 32-bit words)
+ * @out: output (8 32-bit words)
+ * @nrounds: number of rounds (20 or 12; 20 is recommended)
+ *
+ * HChaCha is the ChaCha equivalent of HSalsa and is an intermediate step
+ * towards XChaCha (see https://cr.yp.to/snuffle/xsalsa-20081128.pdf). HChaCha
+ * skips the final addition of the initial state, and outputs only certain words
+ * of the state. It should not be used for streaming directly.
+ */
+void hchacha_block_generic(const u32 *state, u32 *stream, int nrounds)
+{
+ u32 x[16];
+
+ memcpy(x, state, 64);
+
+ chacha_permute(x, nrounds);
+
+ memcpy(&stream[0], &x[0], 16);
+ memcpy(&stream[4], &x[12], 16);
+}
+EXPORT_SYMBOL(hchacha_block_generic);
--- /dev/null
+++ b/lib/crypto/libchacha.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * The ChaCha stream cipher (RFC7539)
+ *
+ * Copyright (C) 2015 Martin Willi
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/module.h>
+
+#include <crypto/algapi.h> // for crypto_xor_cpy
+#include <crypto/chacha.h>
+
+void chacha_crypt_generic(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes, int nrounds)
+{
+ /* aligned to potentially speed up crypto_xor() */
+ u8 stream[CHACHA_BLOCK_SIZE] __aligned(sizeof(long));
+
+ while (bytes >= CHACHA_BLOCK_SIZE) {
+ chacha_block_generic(state, stream, nrounds);
+ crypto_xor_cpy(dst, src, stream, CHACHA_BLOCK_SIZE);
+ bytes -= CHACHA_BLOCK_SIZE;
+ dst += CHACHA_BLOCK_SIZE;
+ src += CHACHA_BLOCK_SIZE;
+ }
+ if (bytes) {
+ chacha_block_generic(state, stream, nrounds);
+ crypto_xor_cpy(dst, src, stream, bytes);
+ }
+}
+EXPORT_SYMBOL(chacha_crypt_generic);
+
+MODULE_LICENSE("GPL");

View File

@@ -1,192 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:09 +0100
Subject: [PATCH] crypto: x86/chacha - depend on generic chacha library instead
of crypto driver
commit 28e8d89b1ce8d2e7badfb5f69971dd635acb8863 upstream.
In preparation of extending the x86 ChaCha driver to also expose the ChaCha
library interface, drop the dependency on the chacha_generic crypto driver
as a non-SIMD fallback, and depend on the generic ChaCha library directly.
This way, we only pull in the code we actually need, without registering
a set of ChaCha skciphers that we will never use.
Since turning the FPU on and off is cheap these days, simplify the SIMD
routine by dropping the per-page yield, which makes for a cleaner switch
to the library API as well. This also allows use to invoke the skcipher
walk routines in non-atomic mode.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/x86/crypto/chacha_glue.c | 90 ++++++++++++++---------------------
crypto/Kconfig | 2 +-
2 files changed, 36 insertions(+), 56 deletions(-)
--- a/arch/x86/crypto/chacha_glue.c
+++ b/arch/x86/crypto/chacha_glue.c
@@ -123,37 +123,38 @@ static void chacha_dosimd(u32 *state, u8
}
}
-static int chacha_simd_stream_xor(struct skcipher_walk *walk,
+static int chacha_simd_stream_xor(struct skcipher_request *req,
const struct chacha_ctx *ctx, const u8 *iv)
{
u32 *state, state_buf[16 + 2] __aligned(8);
- int next_yield = 4096; /* bytes until next FPU yield */
- int err = 0;
+ struct skcipher_walk walk;
+ int err;
+
+ err = skcipher_walk_virt(&walk, req, false);
BUILD_BUG_ON(CHACHA_STATE_ALIGN != 16);
state = PTR_ALIGN(state_buf + 0, CHACHA_STATE_ALIGN);
- crypto_chacha_init(state, ctx, iv);
+ chacha_init_generic(state, ctx->key, iv);
- while (walk->nbytes > 0) {
- unsigned int nbytes = walk->nbytes;
+ while (walk.nbytes > 0) {
+ unsigned int nbytes = walk.nbytes;
- if (nbytes < walk->total) {
- nbytes = round_down(nbytes, walk->stride);
- next_yield -= nbytes;
- }
-
- chacha_dosimd(state, walk->dst.virt.addr, walk->src.virt.addr,
- nbytes, ctx->nrounds);
+ if (nbytes < walk.total)
+ nbytes = round_down(nbytes, walk.stride);
- if (next_yield <= 0) {
- /* temporarily allow preemption */
- kernel_fpu_end();
+ if (!crypto_simd_usable()) {
+ chacha_crypt_generic(state, walk.dst.virt.addr,
+ walk.src.virt.addr, nbytes,
+ ctx->nrounds);
+ } else {
kernel_fpu_begin();
- next_yield = 4096;
+ chacha_dosimd(state, walk.dst.virt.addr,
+ walk.src.virt.addr, nbytes,
+ ctx->nrounds);
+ kernel_fpu_end();
}
-
- err = skcipher_walk_done(walk, walk->nbytes - nbytes);
+ err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
}
return err;
@@ -163,55 +164,34 @@ static int chacha_simd(struct skcipher_r
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
- struct skcipher_walk walk;
- int err;
-
- if (req->cryptlen <= CHACHA_BLOCK_SIZE || !crypto_simd_usable())
- return crypto_chacha_crypt(req);
- err = skcipher_walk_virt(&walk, req, true);
- if (err)
- return err;
-
- kernel_fpu_begin();
- err = chacha_simd_stream_xor(&walk, ctx, req->iv);
- kernel_fpu_end();
- return err;
+ return chacha_simd_stream_xor(req, ctx, req->iv);
}
static int xchacha_simd(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
- struct skcipher_walk walk;
- struct chacha_ctx subctx;
u32 *state, state_buf[16 + 2] __aligned(8);
+ struct chacha_ctx subctx;
u8 real_iv[16];
- int err;
-
- if (req->cryptlen <= CHACHA_BLOCK_SIZE || !crypto_simd_usable())
- return crypto_xchacha_crypt(req);
-
- err = skcipher_walk_virt(&walk, req, true);
- if (err)
- return err;
BUILD_BUG_ON(CHACHA_STATE_ALIGN != 16);
state = PTR_ALIGN(state_buf + 0, CHACHA_STATE_ALIGN);
- crypto_chacha_init(state, ctx, req->iv);
+ chacha_init_generic(state, ctx->key, req->iv);
- kernel_fpu_begin();
-
- hchacha_block_ssse3(state, subctx.key, ctx->nrounds);
+ if (req->cryptlen > CHACHA_BLOCK_SIZE && crypto_simd_usable()) {
+ kernel_fpu_begin();
+ hchacha_block_ssse3(state, subctx.key, ctx->nrounds);
+ kernel_fpu_end();
+ } else {
+ hchacha_block_generic(state, subctx.key, ctx->nrounds);
+ }
subctx.nrounds = ctx->nrounds;
memcpy(&real_iv[0], req->iv + 24, 8);
memcpy(&real_iv[8], req->iv + 16, 8);
- err = chacha_simd_stream_xor(&walk, &subctx, real_iv);
-
- kernel_fpu_end();
-
- return err;
+ return chacha_simd_stream_xor(req, &subctx, real_iv);
}
static struct skcipher_alg algs[] = {
@@ -227,7 +207,7 @@ static struct skcipher_alg algs[] = {
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = CHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha20_setkey,
+ .setkey = chacha20_setkey,
.encrypt = chacha_simd,
.decrypt = chacha_simd,
}, {
@@ -242,7 +222,7 @@ static struct skcipher_alg algs[] = {
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha20_setkey,
+ .setkey = chacha20_setkey,
.encrypt = xchacha_simd,
.decrypt = xchacha_simd,
}, {
@@ -257,7 +237,7 @@ static struct skcipher_alg algs[] = {
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha12_setkey,
+ .setkey = chacha12_setkey,
.encrypt = xchacha_simd,
.decrypt = xchacha_simd,
},
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1417,7 +1417,7 @@ config CRYPTO_CHACHA20_X86_64
tristate "ChaCha stream cipher algorithms (x86_64/SSSE3/AVX2/AVX-512VL)"
depends on X86 && 64BIT
select CRYPTO_BLKCIPHER
- select CRYPTO_CHACHA20
+ select CRYPTO_LIB_CHACHA_GENERIC
help
SSSE3, AVX2, and AVX-512VL optimized implementations of the ChaCha20,
XChaCha20, and XChaCha12 stream ciphers.

View File

@@ -1,205 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:10 +0100
Subject: [PATCH] crypto: x86/chacha - expose SIMD ChaCha routine as library
function
commit 84e03fa39fbe95a5567d43bff458c6d3b3a23ad1 upstream.
Wire the existing x86 SIMD ChaCha code into the new ChaCha library
interface, so that users of the library interface will get the
accelerated version when available.
Given that calls into the library API will always go through the
routines in this module if it is enabled, switch to static keys
to select the optimal implementation available (which may be none
at all, in which case we defer to the generic implementation for
all invocations).
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/x86/crypto/chacha_glue.c | 91 +++++++++++++++++++++++++----------
crypto/Kconfig | 1 +
include/crypto/chacha.h | 6 +++
3 files changed, 73 insertions(+), 25 deletions(-)
--- a/arch/x86/crypto/chacha_glue.c
+++ b/arch/x86/crypto/chacha_glue.c
@@ -21,24 +21,24 @@ asmlinkage void chacha_block_xor_ssse3(u
asmlinkage void chacha_4block_xor_ssse3(u32 *state, u8 *dst, const u8 *src,
unsigned int len, int nrounds);
asmlinkage void hchacha_block_ssse3(const u32 *state, u32 *out, int nrounds);
-#ifdef CONFIG_AS_AVX2
+
asmlinkage void chacha_2block_xor_avx2(u32 *state, u8 *dst, const u8 *src,
unsigned int len, int nrounds);
asmlinkage void chacha_4block_xor_avx2(u32 *state, u8 *dst, const u8 *src,
unsigned int len, int nrounds);
asmlinkage void chacha_8block_xor_avx2(u32 *state, u8 *dst, const u8 *src,
unsigned int len, int nrounds);
-static bool chacha_use_avx2;
-#ifdef CONFIG_AS_AVX512
+
asmlinkage void chacha_2block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src,
unsigned int len, int nrounds);
asmlinkage void chacha_4block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src,
unsigned int len, int nrounds);
asmlinkage void chacha_8block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src,
unsigned int len, int nrounds);
-static bool chacha_use_avx512vl;
-#endif
-#endif
+
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(chacha_use_simd);
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(chacha_use_avx2);
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(chacha_use_avx512vl);
static unsigned int chacha_advance(unsigned int len, unsigned int maxblocks)
{
@@ -49,9 +49,8 @@ static unsigned int chacha_advance(unsig
static void chacha_dosimd(u32 *state, u8 *dst, const u8 *src,
unsigned int bytes, int nrounds)
{
-#ifdef CONFIG_AS_AVX2
-#ifdef CONFIG_AS_AVX512
- if (chacha_use_avx512vl) {
+ if (IS_ENABLED(CONFIG_AS_AVX512) &&
+ static_branch_likely(&chacha_use_avx512vl)) {
while (bytes >= CHACHA_BLOCK_SIZE * 8) {
chacha_8block_xor_avx512vl(state, dst, src, bytes,
nrounds);
@@ -79,8 +78,9 @@ static void chacha_dosimd(u32 *state, u8
return;
}
}
-#endif
- if (chacha_use_avx2) {
+
+ if (IS_ENABLED(CONFIG_AS_AVX2) &&
+ static_branch_likely(&chacha_use_avx2)) {
while (bytes >= CHACHA_BLOCK_SIZE * 8) {
chacha_8block_xor_avx2(state, dst, src, bytes, nrounds);
bytes -= CHACHA_BLOCK_SIZE * 8;
@@ -104,7 +104,7 @@ static void chacha_dosimd(u32 *state, u8
return;
}
}
-#endif
+
while (bytes >= CHACHA_BLOCK_SIZE * 4) {
chacha_4block_xor_ssse3(state, dst, src, bytes, nrounds);
bytes -= CHACHA_BLOCK_SIZE * 4;
@@ -123,6 +123,43 @@ static void chacha_dosimd(u32 *state, u8
}
}
+void hchacha_block_arch(const u32 *state, u32 *stream, int nrounds)
+{
+ state = PTR_ALIGN(state, CHACHA_STATE_ALIGN);
+
+ if (!static_branch_likely(&chacha_use_simd) || !crypto_simd_usable()) {
+ hchacha_block_generic(state, stream, nrounds);
+ } else {
+ kernel_fpu_begin();
+ hchacha_block_ssse3(state, stream, nrounds);
+ kernel_fpu_end();
+ }
+}
+EXPORT_SYMBOL(hchacha_block_arch);
+
+void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv)
+{
+ state = PTR_ALIGN(state, CHACHA_STATE_ALIGN);
+
+ chacha_init_generic(state, key, iv);
+}
+EXPORT_SYMBOL(chacha_init_arch);
+
+void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
+ int nrounds)
+{
+ state = PTR_ALIGN(state, CHACHA_STATE_ALIGN);
+
+ if (!static_branch_likely(&chacha_use_simd) || !crypto_simd_usable() ||
+ bytes <= CHACHA_BLOCK_SIZE)
+ return chacha_crypt_generic(state, dst, src, bytes, nrounds);
+
+ kernel_fpu_begin();
+ chacha_dosimd(state, dst, src, bytes, nrounds);
+ kernel_fpu_end();
+}
+EXPORT_SYMBOL(chacha_crypt_arch);
+
static int chacha_simd_stream_xor(struct skcipher_request *req,
const struct chacha_ctx *ctx, const u8 *iv)
{
@@ -143,7 +180,8 @@ static int chacha_simd_stream_xor(struct
if (nbytes < walk.total)
nbytes = round_down(nbytes, walk.stride);
- if (!crypto_simd_usable()) {
+ if (!static_branch_likely(&chacha_use_simd) ||
+ !crypto_simd_usable()) {
chacha_crypt_generic(state, walk.dst.virt.addr,
walk.src.virt.addr, nbytes,
ctx->nrounds);
@@ -246,18 +284,21 @@ static struct skcipher_alg algs[] = {
static int __init chacha_simd_mod_init(void)
{
if (!boot_cpu_has(X86_FEATURE_SSSE3))
- return -ENODEV;
+ return 0;
-#ifdef CONFIG_AS_AVX2
- chacha_use_avx2 = boot_cpu_has(X86_FEATURE_AVX) &&
- boot_cpu_has(X86_FEATURE_AVX2) &&
- cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL);
-#ifdef CONFIG_AS_AVX512
- chacha_use_avx512vl = chacha_use_avx2 &&
- boot_cpu_has(X86_FEATURE_AVX512VL) &&
- boot_cpu_has(X86_FEATURE_AVX512BW); /* kmovq */
-#endif
-#endif
+ static_branch_enable(&chacha_use_simd);
+
+ if (IS_ENABLED(CONFIG_AS_AVX2) &&
+ boot_cpu_has(X86_FEATURE_AVX) &&
+ boot_cpu_has(X86_FEATURE_AVX2) &&
+ cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) {
+ static_branch_enable(&chacha_use_avx2);
+
+ if (IS_ENABLED(CONFIG_AS_AVX512) &&
+ boot_cpu_has(X86_FEATURE_AVX512VL) &&
+ boot_cpu_has(X86_FEATURE_AVX512BW)) /* kmovq */
+ static_branch_enable(&chacha_use_avx512vl);
+ }
return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
}
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1418,6 +1418,7 @@ config CRYPTO_CHACHA20_X86_64
depends on X86 && 64BIT
select CRYPTO_BLKCIPHER
select CRYPTO_LIB_CHACHA_GENERIC
+ select CRYPTO_ARCH_HAVE_LIB_CHACHA
help
SSSE3, AVX2, and AVX-512VL optimized implementations of the ChaCha20,
XChaCha20, and XChaCha12 stream ciphers.
--- a/include/crypto/chacha.h
+++ b/include/crypto/chacha.h
@@ -25,6 +25,12 @@
#define CHACHA_BLOCK_SIZE 64
#define CHACHAPOLY_IV_SIZE 12
+#ifdef CONFIG_X86_64
+#define CHACHA_STATE_WORDS ((CHACHA_BLOCK_SIZE + 12) / sizeof(u32))
+#else
+#define CHACHA_STATE_WORDS (CHACHA_BLOCK_SIZE / sizeof(u32))
+#endif
+
/* 192-bit nonce, then 64-bit stream position */
#define XCHACHA_IV_SIZE 32

View File

@@ -1,129 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:11 +0100
Subject: [PATCH] crypto: arm64/chacha - depend on generic chacha library
instead of crypto driver
commit c77da4867cbb7841177275dbb250f5c09679fae4 upstream.
Depend on the generic ChaCha library routines instead of pulling in the
generic ChaCha skcipher driver, which is more than we need, and makes
managing the dependencies between the generic library, generic driver,
accelerated library and driver more complicated.
While at it, drop the logic to prefer the scalar code on short inputs.
Turning the NEON on and off is cheap these days, and one major use case
for ChaCha20 is ChaCha20-Poly1305, which is guaranteed to hit the scalar
path upon every invocation (when doing the Poly1305 nonce generation)
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/arm64/crypto/Kconfig | 2 +-
arch/arm64/crypto/chacha-neon-glue.c | 40 +++++++++++++++-------------
2 files changed, 23 insertions(+), 19 deletions(-)
--- a/arch/arm64/crypto/Kconfig
+++ b/arch/arm64/crypto/Kconfig
@@ -103,7 +103,7 @@ config CRYPTO_CHACHA20_NEON
tristate "ChaCha20, XChaCha20, and XChaCha12 stream ciphers using NEON instructions"
depends on KERNEL_MODE_NEON
select CRYPTO_BLKCIPHER
- select CRYPTO_CHACHA20
+ select CRYPTO_LIB_CHACHA_GENERIC
config CRYPTO_NHPOLY1305_NEON
tristate "NHPoly1305 hash function using NEON instructions (for Adiantum)"
--- a/arch/arm64/crypto/chacha-neon-glue.c
+++ b/arch/arm64/crypto/chacha-neon-glue.c
@@ -68,7 +68,7 @@ static int chacha_neon_stream_xor(struct
err = skcipher_walk_virt(&walk, req, false);
- crypto_chacha_init(state, ctx, iv);
+ chacha_init_generic(state, ctx->key, iv);
while (walk.nbytes > 0) {
unsigned int nbytes = walk.nbytes;
@@ -76,10 +76,16 @@ static int chacha_neon_stream_xor(struct
if (nbytes < walk.total)
nbytes = rounddown(nbytes, walk.stride);
- kernel_neon_begin();
- chacha_doneon(state, walk.dst.virt.addr, walk.src.virt.addr,
- nbytes, ctx->nrounds);
- kernel_neon_end();
+ if (!crypto_simd_usable()) {
+ chacha_crypt_generic(state, walk.dst.virt.addr,
+ walk.src.virt.addr, nbytes,
+ ctx->nrounds);
+ } else {
+ kernel_neon_begin();
+ chacha_doneon(state, walk.dst.virt.addr,
+ walk.src.virt.addr, nbytes, ctx->nrounds);
+ kernel_neon_end();
+ }
err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
}
@@ -91,9 +97,6 @@ static int chacha_neon(struct skcipher_r
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
- if (req->cryptlen <= CHACHA_BLOCK_SIZE || !crypto_simd_usable())
- return crypto_chacha_crypt(req);
-
return chacha_neon_stream_xor(req, ctx, req->iv);
}
@@ -105,14 +108,15 @@ static int xchacha_neon(struct skcipher_
u32 state[16];
u8 real_iv[16];
- if (req->cryptlen <= CHACHA_BLOCK_SIZE || !crypto_simd_usable())
- return crypto_xchacha_crypt(req);
-
- crypto_chacha_init(state, ctx, req->iv);
+ chacha_init_generic(state, ctx->key, req->iv);
- kernel_neon_begin();
- hchacha_block_neon(state, subctx.key, ctx->nrounds);
- kernel_neon_end();
+ if (crypto_simd_usable()) {
+ kernel_neon_begin();
+ hchacha_block_neon(state, subctx.key, ctx->nrounds);
+ kernel_neon_end();
+ } else {
+ hchacha_block_generic(state, subctx.key, ctx->nrounds);
+ }
subctx.nrounds = ctx->nrounds;
memcpy(&real_iv[0], req->iv + 24, 8);
@@ -134,7 +138,7 @@ static struct skcipher_alg algs[] = {
.ivsize = CHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 5 * CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha20_setkey,
+ .setkey = chacha20_setkey,
.encrypt = chacha_neon,
.decrypt = chacha_neon,
}, {
@@ -150,7 +154,7 @@ static struct skcipher_alg algs[] = {
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 5 * CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha20_setkey,
+ .setkey = chacha20_setkey,
.encrypt = xchacha_neon,
.decrypt = xchacha_neon,
}, {
@@ -166,7 +170,7 @@ static struct skcipher_alg algs[] = {
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 5 * CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha12_setkey,
+ .setkey = chacha12_setkey,
.encrypt = xchacha_neon,
.decrypt = xchacha_neon,
}

View File

@@ -1,138 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:12 +0100
Subject: [PATCH] crypto: arm64/chacha - expose arm64 ChaCha routine as library
function
commit b3aad5bad26a01a4bd8c49a5c5f52aec665f3b7c upstream.
Expose the accelerated NEON ChaCha routine directly as a symbol
export so that users of the ChaCha library API can use it directly.
Given that calls into the library API will always go through the
routines in this module if it is enabled, switch to static keys
to select the optimal implementation available (which may be none
at all, in which case we defer to the generic implementation for
all invocations).
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/arm64/crypto/Kconfig | 1 +
arch/arm64/crypto/chacha-neon-glue.c | 53 ++++++++++++++++++++++------
2 files changed, 43 insertions(+), 11 deletions(-)
--- a/arch/arm64/crypto/Kconfig
+++ b/arch/arm64/crypto/Kconfig
@@ -104,6 +104,7 @@ config CRYPTO_CHACHA20_NEON
depends on KERNEL_MODE_NEON
select CRYPTO_BLKCIPHER
select CRYPTO_LIB_CHACHA_GENERIC
+ select CRYPTO_ARCH_HAVE_LIB_CHACHA
config CRYPTO_NHPOLY1305_NEON
tristate "NHPoly1305 hash function using NEON instructions (for Adiantum)"
--- a/arch/arm64/crypto/chacha-neon-glue.c
+++ b/arch/arm64/crypto/chacha-neon-glue.c
@@ -23,6 +23,7 @@
#include <crypto/internal/chacha.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
+#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -36,6 +37,8 @@ asmlinkage void chacha_4block_xor_neon(u
int nrounds, int bytes);
asmlinkage void hchacha_block_neon(const u32 *state, u32 *out, int nrounds);
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
+
static void chacha_doneon(u32 *state, u8 *dst, const u8 *src,
int bytes, int nrounds)
{
@@ -59,6 +62,37 @@ static void chacha_doneon(u32 *state, u8
}
}
+void hchacha_block_arch(const u32 *state, u32 *stream, int nrounds)
+{
+ if (!static_branch_likely(&have_neon) || !crypto_simd_usable()) {
+ hchacha_block_generic(state, stream, nrounds);
+ } else {
+ kernel_neon_begin();
+ hchacha_block_neon(state, stream, nrounds);
+ kernel_neon_end();
+ }
+}
+EXPORT_SYMBOL(hchacha_block_arch);
+
+void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv)
+{
+ chacha_init_generic(state, key, iv);
+}
+EXPORT_SYMBOL(chacha_init_arch);
+
+void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
+ int nrounds)
+{
+ if (!static_branch_likely(&have_neon) || bytes <= CHACHA_BLOCK_SIZE ||
+ !crypto_simd_usable())
+ return chacha_crypt_generic(state, dst, src, bytes, nrounds);
+
+ kernel_neon_begin();
+ chacha_doneon(state, dst, src, bytes, nrounds);
+ kernel_neon_end();
+}
+EXPORT_SYMBOL(chacha_crypt_arch);
+
static int chacha_neon_stream_xor(struct skcipher_request *req,
const struct chacha_ctx *ctx, const u8 *iv)
{
@@ -76,7 +110,8 @@ static int chacha_neon_stream_xor(struct
if (nbytes < walk.total)
nbytes = rounddown(nbytes, walk.stride);
- if (!crypto_simd_usable()) {
+ if (!static_branch_likely(&have_neon) ||
+ !crypto_simd_usable()) {
chacha_crypt_generic(state, walk.dst.virt.addr,
walk.src.virt.addr, nbytes,
ctx->nrounds);
@@ -109,14 +144,7 @@ static int xchacha_neon(struct skcipher_
u8 real_iv[16];
chacha_init_generic(state, ctx->key, req->iv);
-
- if (crypto_simd_usable()) {
- kernel_neon_begin();
- hchacha_block_neon(state, subctx.key, ctx->nrounds);
- kernel_neon_end();
- } else {
- hchacha_block_generic(state, subctx.key, ctx->nrounds);
- }
+ hchacha_block_arch(state, subctx.key, ctx->nrounds);
subctx.nrounds = ctx->nrounds;
memcpy(&real_iv[0], req->iv + 24, 8);
@@ -179,14 +207,17 @@ static struct skcipher_alg algs[] = {
static int __init chacha_simd_mod_init(void)
{
if (!cpu_have_named_feature(ASIMD))
- return -ENODEV;
+ return 0;
+
+ static_branch_enable(&have_neon);
return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
}
static void __exit chacha_simd_mod_fini(void)
{
- crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
+ if (cpu_have_named_feature(ASIMD))
+ crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
}
module_init(chacha_simd_mod_init);

View File

@@ -1,480 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:13 +0100
Subject: [PATCH] crypto: arm/chacha - import Eric Biggers's scalar accelerated
ChaCha code
commit 29621d099f9c642b22a69dc8e7e20c108473a392 upstream.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/arm/crypto/chacha-scalar-core.S | 461 +++++++++++++++++++++++++++
1 file changed, 461 insertions(+)
create mode 100644 arch/arm/crypto/chacha-scalar-core.S
--- /dev/null
+++ b/arch/arm/crypto/chacha-scalar-core.S
@@ -0,0 +1,461 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Google, Inc.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Design notes:
+ *
+ * 16 registers would be needed to hold the state matrix, but only 14 are
+ * available because 'sp' and 'pc' cannot be used. So we spill the elements
+ * (x8, x9) to the stack and swap them out with (x10, x11). This adds one
+ * 'ldrd' and one 'strd' instruction per round.
+ *
+ * All rotates are performed using the implicit rotate operand accepted by the
+ * 'add' and 'eor' instructions. This is faster than using explicit rotate
+ * instructions. To make this work, we allow the values in the second and last
+ * rows of the ChaCha state matrix (rows 'b' and 'd') to temporarily have the
+ * wrong rotation amount. The rotation amount is then fixed up just in time
+ * when the values are used. 'brot' is the number of bits the values in row 'b'
+ * need to be rotated right to arrive at the correct values, and 'drot'
+ * similarly for row 'd'. (brot, drot) start out as (0, 0) but we make it such
+ * that they end up as (25, 24) after every round.
+ */
+
+ // ChaCha state registers
+ X0 .req r0
+ X1 .req r1
+ X2 .req r2
+ X3 .req r3
+ X4 .req r4
+ X5 .req r5
+ X6 .req r6
+ X7 .req r7
+ X8_X10 .req r8 // shared by x8 and x10
+ X9_X11 .req r9 // shared by x9 and x11
+ X12 .req r10
+ X13 .req r11
+ X14 .req r12
+ X15 .req r14
+
+.Lexpand_32byte_k:
+ // "expand 32-byte k"
+ .word 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
+
+#ifdef __thumb2__
+# define adrl adr
+#endif
+
+.macro __rev out, in, t0, t1, t2
+.if __LINUX_ARM_ARCH__ >= 6
+ rev \out, \in
+.else
+ lsl \t0, \in, #24
+ and \t1, \in, #0xff00
+ and \t2, \in, #0xff0000
+ orr \out, \t0, \in, lsr #24
+ orr \out, \out, \t1, lsl #8
+ orr \out, \out, \t2, lsr #8
+.endif
+.endm
+
+.macro _le32_bswap x, t0, t1, t2
+#ifdef __ARMEB__
+ __rev \x, \x, \t0, \t1, \t2
+#endif
+.endm
+
+.macro _le32_bswap_4x a, b, c, d, t0, t1, t2
+ _le32_bswap \a, \t0, \t1, \t2
+ _le32_bswap \b, \t0, \t1, \t2
+ _le32_bswap \c, \t0, \t1, \t2
+ _le32_bswap \d, \t0, \t1, \t2
+.endm
+
+.macro __ldrd a, b, src, offset
+#if __LINUX_ARM_ARCH__ >= 6
+ ldrd \a, \b, [\src, #\offset]
+#else
+ ldr \a, [\src, #\offset]
+ ldr \b, [\src, #\offset + 4]
+#endif
+.endm
+
+.macro __strd a, b, dst, offset
+#if __LINUX_ARM_ARCH__ >= 6
+ strd \a, \b, [\dst, #\offset]
+#else
+ str \a, [\dst, #\offset]
+ str \b, [\dst, #\offset + 4]
+#endif
+.endm
+
+.macro _halfround a1, b1, c1, d1, a2, b2, c2, d2
+
+ // a += b; d ^= a; d = rol(d, 16);
+ add \a1, \a1, \b1, ror #brot
+ add \a2, \a2, \b2, ror #brot
+ eor \d1, \a1, \d1, ror #drot
+ eor \d2, \a2, \d2, ror #drot
+ // drot == 32 - 16 == 16
+
+ // c += d; b ^= c; b = rol(b, 12);
+ add \c1, \c1, \d1, ror #16
+ add \c2, \c2, \d2, ror #16
+ eor \b1, \c1, \b1, ror #brot
+ eor \b2, \c2, \b2, ror #brot
+ // brot == 32 - 12 == 20
+
+ // a += b; d ^= a; d = rol(d, 8);
+ add \a1, \a1, \b1, ror #20
+ add \a2, \a2, \b2, ror #20
+ eor \d1, \a1, \d1, ror #16
+ eor \d2, \a2, \d2, ror #16
+ // drot == 32 - 8 == 24
+
+ // c += d; b ^= c; b = rol(b, 7);
+ add \c1, \c1, \d1, ror #24
+ add \c2, \c2, \d2, ror #24
+ eor \b1, \c1, \b1, ror #20
+ eor \b2, \c2, \b2, ror #20
+ // brot == 32 - 7 == 25
+.endm
+
+.macro _doubleround
+
+ // column round
+
+ // quarterrounds: (x0, x4, x8, x12) and (x1, x5, x9, x13)
+ _halfround X0, X4, X8_X10, X12, X1, X5, X9_X11, X13
+
+ // save (x8, x9); restore (x10, x11)
+ __strd X8_X10, X9_X11, sp, 0
+ __ldrd X8_X10, X9_X11, sp, 8
+
+ // quarterrounds: (x2, x6, x10, x14) and (x3, x7, x11, x15)
+ _halfround X2, X6, X8_X10, X14, X3, X7, X9_X11, X15
+
+ .set brot, 25
+ .set drot, 24
+
+ // diagonal round
+
+ // quarterrounds: (x0, x5, x10, x15) and (x1, x6, x11, x12)
+ _halfround X0, X5, X8_X10, X15, X1, X6, X9_X11, X12
+
+ // save (x10, x11); restore (x8, x9)
+ __strd X8_X10, X9_X11, sp, 8
+ __ldrd X8_X10, X9_X11, sp, 0
+
+ // quarterrounds: (x2, x7, x8, x13) and (x3, x4, x9, x14)
+ _halfround X2, X7, X8_X10, X13, X3, X4, X9_X11, X14
+.endm
+
+.macro _chacha_permute nrounds
+ .set brot, 0
+ .set drot, 0
+ .rept \nrounds / 2
+ _doubleround
+ .endr
+.endm
+
+.macro _chacha nrounds
+
+.Lnext_block\@:
+ // Stack: unused0-unused1 x10-x11 x0-x15 OUT IN LEN
+ // Registers contain x0-x9,x12-x15.
+
+ // Do the core ChaCha permutation to update x0-x15.
+ _chacha_permute \nrounds
+
+ add sp, #8
+ // Stack: x10-x11 orig_x0-orig_x15 OUT IN LEN
+ // Registers contain x0-x9,x12-x15.
+ // x4-x7 are rotated by 'brot'; x12-x15 are rotated by 'drot'.
+
+ // Free up some registers (r8-r12,r14) by pushing (x8-x9,x12-x15).
+ push {X8_X10, X9_X11, X12, X13, X14, X15}
+
+ // Load (OUT, IN, LEN).
+ ldr r14, [sp, #96]
+ ldr r12, [sp, #100]
+ ldr r11, [sp, #104]
+
+ orr r10, r14, r12
+
+ // Use slow path if fewer than 64 bytes remain.
+ cmp r11, #64
+ blt .Lxor_slowpath\@
+
+ // Use slow path if IN and/or OUT isn't 4-byte aligned. Needed even on
+ // ARMv6+, since ldmia and stmia (used below) still require alignment.
+ tst r10, #3
+ bne .Lxor_slowpath\@
+
+ // Fast path: XOR 64 bytes of aligned data.
+
+ // Stack: x8-x9 x12-x15 x10-x11 orig_x0-orig_x15 OUT IN LEN
+ // Registers: r0-r7 are x0-x7; r8-r11 are free; r12 is IN; r14 is OUT.
+ // x4-x7 are rotated by 'brot'; x12-x15 are rotated by 'drot'.
+
+ // x0-x3
+ __ldrd r8, r9, sp, 32
+ __ldrd r10, r11, sp, 40
+ add X0, X0, r8
+ add X1, X1, r9
+ add X2, X2, r10
+ add X3, X3, r11
+ _le32_bswap_4x X0, X1, X2, X3, r8, r9, r10
+ ldmia r12!, {r8-r11}
+ eor X0, X0, r8
+ eor X1, X1, r9
+ eor X2, X2, r10
+ eor X3, X3, r11
+ stmia r14!, {X0-X3}
+
+ // x4-x7
+ __ldrd r8, r9, sp, 48
+ __ldrd r10, r11, sp, 56
+ add X4, r8, X4, ror #brot
+ add X5, r9, X5, ror #brot
+ ldmia r12!, {X0-X3}
+ add X6, r10, X6, ror #brot
+ add X7, r11, X7, ror #brot
+ _le32_bswap_4x X4, X5, X6, X7, r8, r9, r10
+ eor X4, X4, X0
+ eor X5, X5, X1
+ eor X6, X6, X2
+ eor X7, X7, X3
+ stmia r14!, {X4-X7}
+
+ // x8-x15
+ pop {r0-r7} // (x8-x9,x12-x15,x10-x11)
+ __ldrd r8, r9, sp, 32
+ __ldrd r10, r11, sp, 40
+ add r0, r0, r8 // x8
+ add r1, r1, r9 // x9
+ add r6, r6, r10 // x10
+ add r7, r7, r11 // x11
+ _le32_bswap_4x r0, r1, r6, r7, r8, r9, r10
+ ldmia r12!, {r8-r11}
+ eor r0, r0, r8 // x8
+ eor r1, r1, r9 // x9
+ eor r6, r6, r10 // x10
+ eor r7, r7, r11 // x11
+ stmia r14!, {r0,r1,r6,r7}
+ ldmia r12!, {r0,r1,r6,r7}
+ __ldrd r8, r9, sp, 48
+ __ldrd r10, r11, sp, 56
+ add r2, r8, r2, ror #drot // x12
+ add r3, r9, r3, ror #drot // x13
+ add r4, r10, r4, ror #drot // x14
+ add r5, r11, r5, ror #drot // x15
+ _le32_bswap_4x r2, r3, r4, r5, r9, r10, r11
+ ldr r9, [sp, #72] // load LEN
+ eor r2, r2, r0 // x12
+ eor r3, r3, r1 // x13
+ eor r4, r4, r6 // x14
+ eor r5, r5, r7 // x15
+ subs r9, #64 // decrement and check LEN
+ stmia r14!, {r2-r5}
+
+ beq .Ldone\@
+
+.Lprepare_for_next_block\@:
+
+ // Stack: x0-x15 OUT IN LEN
+
+ // Increment block counter (x12)
+ add r8, #1
+
+ // Store updated (OUT, IN, LEN)
+ str r14, [sp, #64]
+ str r12, [sp, #68]
+ str r9, [sp, #72]
+
+ mov r14, sp
+
+ // Store updated block counter (x12)
+ str r8, [sp, #48]
+
+ sub sp, #16
+
+ // Reload state and do next block
+ ldmia r14!, {r0-r11} // load x0-x11
+ __strd r10, r11, sp, 8 // store x10-x11 before state
+ ldmia r14, {r10-r12,r14} // load x12-x15
+ b .Lnext_block\@
+
+.Lxor_slowpath\@:
+ // Slow path: < 64 bytes remaining, or unaligned input or output buffer.
+ // We handle it by storing the 64 bytes of keystream to the stack, then
+ // XOR-ing the needed portion with the data.
+
+ // Allocate keystream buffer
+ sub sp, #64
+ mov r14, sp
+
+ // Stack: ks0-ks15 x8-x9 x12-x15 x10-x11 orig_x0-orig_x15 OUT IN LEN
+ // Registers: r0-r7 are x0-x7; r8-r11 are free; r12 is IN; r14 is &ks0.
+ // x4-x7 are rotated by 'brot'; x12-x15 are rotated by 'drot'.
+
+ // Save keystream for x0-x3
+ __ldrd r8, r9, sp, 96
+ __ldrd r10, r11, sp, 104
+ add X0, X0, r8
+ add X1, X1, r9
+ add X2, X2, r10
+ add X3, X3, r11
+ _le32_bswap_4x X0, X1, X2, X3, r8, r9, r10
+ stmia r14!, {X0-X3}
+
+ // Save keystream for x4-x7
+ __ldrd r8, r9, sp, 112
+ __ldrd r10, r11, sp, 120
+ add X4, r8, X4, ror #brot
+ add X5, r9, X5, ror #brot
+ add X6, r10, X6, ror #brot
+ add X7, r11, X7, ror #brot
+ _le32_bswap_4x X4, X5, X6, X7, r8, r9, r10
+ add r8, sp, #64
+ stmia r14!, {X4-X7}
+
+ // Save keystream for x8-x15
+ ldm r8, {r0-r7} // (x8-x9,x12-x15,x10-x11)
+ __ldrd r8, r9, sp, 128
+ __ldrd r10, r11, sp, 136
+ add r0, r0, r8 // x8
+ add r1, r1, r9 // x9
+ add r6, r6, r10 // x10
+ add r7, r7, r11 // x11
+ _le32_bswap_4x r0, r1, r6, r7, r8, r9, r10
+ stmia r14!, {r0,r1,r6,r7}
+ __ldrd r8, r9, sp, 144
+ __ldrd r10, r11, sp, 152
+ add r2, r8, r2, ror #drot // x12
+ add r3, r9, r3, ror #drot // x13
+ add r4, r10, r4, ror #drot // x14
+ add r5, r11, r5, ror #drot // x15
+ _le32_bswap_4x r2, r3, r4, r5, r9, r10, r11
+ stmia r14, {r2-r5}
+
+ // Stack: ks0-ks15 unused0-unused7 x0-x15 OUT IN LEN
+ // Registers: r8 is block counter, r12 is IN.
+
+ ldr r9, [sp, #168] // LEN
+ ldr r14, [sp, #160] // OUT
+ cmp r9, #64
+ mov r0, sp
+ movle r1, r9
+ movgt r1, #64
+ // r1 is number of bytes to XOR, in range [1, 64]
+
+.if __LINUX_ARM_ARCH__ < 6
+ orr r2, r12, r14
+ tst r2, #3 // IN or OUT misaligned?
+ bne .Lxor_next_byte\@
+.endif
+
+ // XOR a word at a time
+.rept 16
+ subs r1, #4
+ blt .Lxor_words_done\@
+ ldr r2, [r12], #4
+ ldr r3, [r0], #4
+ eor r2, r2, r3
+ str r2, [r14], #4
+.endr
+ b .Lxor_slowpath_done\@
+.Lxor_words_done\@:
+ ands r1, r1, #3
+ beq .Lxor_slowpath_done\@
+
+ // XOR a byte at a time
+.Lxor_next_byte\@:
+ ldrb r2, [r12], #1
+ ldrb r3, [r0], #1
+ eor r2, r2, r3
+ strb r2, [r14], #1
+ subs r1, #1
+ bne .Lxor_next_byte\@
+
+.Lxor_slowpath_done\@:
+ subs r9, #64
+ add sp, #96
+ bgt .Lprepare_for_next_block\@
+
+.Ldone\@:
+.endm // _chacha
+
+/*
+ * void chacha20_arm(u8 *out, const u8 *in, size_t len, const u32 key[8],
+ * const u32 iv[4]);
+ */
+ENTRY(chacha20_arm)
+ cmp r2, #0 // len == 0?
+ reteq lr
+
+ push {r0-r2,r4-r11,lr}
+
+ // Push state x0-x15 onto stack.
+ // Also store an extra copy of x10-x11 just before the state.
+
+ ldr r4, [sp, #48] // iv
+ mov r0, sp
+ sub sp, #80
+
+ // iv: x12-x15
+ ldm r4, {X12,X13,X14,X15}
+ stmdb r0!, {X12,X13,X14,X15}
+
+ // key: x4-x11
+ __ldrd X8_X10, X9_X11, r3, 24
+ __strd X8_X10, X9_X11, sp, 8
+ stmdb r0!, {X8_X10, X9_X11}
+ ldm r3, {X4-X9_X11}
+ stmdb r0!, {X4-X9_X11}
+
+ // constants: x0-x3
+ adrl X3, .Lexpand_32byte_k
+ ldm X3, {X0-X3}
+ __strd X0, X1, sp, 16
+ __strd X2, X3, sp, 24
+
+ _chacha 20
+
+ add sp, #76
+ pop {r4-r11, pc}
+ENDPROC(chacha20_arm)
+
+/*
+ * void hchacha20_arm(const u32 state[16], u32 out[8]);
+ */
+ENTRY(hchacha20_arm)
+ push {r1,r4-r11,lr}
+
+ mov r14, r0
+ ldmia r14!, {r0-r11} // load x0-x11
+ push {r10-r11} // store x10-x11 to stack
+ ldm r14, {r10-r12,r14} // load x12-x15
+ sub sp, #8
+
+ _chacha_permute 20
+
+ // Skip over (unused0-unused1, x10-x11)
+ add sp, #16
+
+ // Fix up rotations of x12-x15
+ ror X12, X12, #drot
+ ror X13, X13, #drot
+ pop {r4} // load 'out'
+ ror X14, X14, #drot
+ ror X15, X15, #drot
+
+ // Store (x0-x3,x12-x15) to 'out'
+ stm r4, {X0,X1,X2,X3,X12,X13,X14,X15}
+
+ pop {r4-r11,pc}
+ENDPROC(hchacha20_arm)

View File

@@ -1,691 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:14 +0100
Subject: [PATCH] crypto: arm/chacha - remove dependency on generic ChaCha
driver
commit b36d8c09e710c71f6a9690b6586fea2d1c9e1e27 upstream.
Instead of falling back to the generic ChaCha skcipher driver for
non-SIMD cases, use a fast scalar implementation for ARM authored
by Eric Biggers. This removes the module dependency on chacha-generic
altogether, which also simplifies things when we expose the ChaCha
library interface from this module.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/arm/crypto/Kconfig | 4 +-
arch/arm/crypto/Makefile | 3 +-
arch/arm/crypto/chacha-glue.c | 304 +++++++++++++++++++++++++++
arch/arm/crypto/chacha-neon-glue.c | 202 ------------------
arch/arm/crypto/chacha-scalar-core.S | 65 +++---
arch/arm64/crypto/chacha-neon-glue.c | 2 +-
6 files changed, 340 insertions(+), 240 deletions(-)
create mode 100644 arch/arm/crypto/chacha-glue.c
delete mode 100644 arch/arm/crypto/chacha-neon-glue.c
--- a/arch/arm/crypto/Kconfig
+++ b/arch/arm/crypto/Kconfig
@@ -127,10 +127,8 @@ config CRYPTO_CRC32_ARM_CE
select CRYPTO_HASH
config CRYPTO_CHACHA20_NEON
- tristate "NEON accelerated ChaCha stream cipher algorithms"
- depends on KERNEL_MODE_NEON
+ tristate "NEON and scalar accelerated ChaCha stream cipher algorithms"
select CRYPTO_BLKCIPHER
- select CRYPTO_CHACHA20
config CRYPTO_NHPOLY1305_NEON
tristate "NEON accelerated NHPoly1305 hash function (for Adiantum)"
--- a/arch/arm/crypto/Makefile
+++ b/arch/arm/crypto/Makefile
@@ -53,7 +53,8 @@ aes-arm-ce-y := aes-ce-core.o aes-ce-glu
ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o
crct10dif-arm-ce-y := crct10dif-ce-core.o crct10dif-ce-glue.o
crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o
-chacha-neon-y := chacha-neon-core.o chacha-neon-glue.o
+chacha-neon-y := chacha-scalar-core.o chacha-glue.o
+chacha-neon-$(CONFIG_KERNEL_MODE_NEON) += chacha-neon-core.o
nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o
ifdef REGENERATE_ARM_CRYPTO
--- /dev/null
+++ b/arch/arm/crypto/chacha-glue.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM NEON accelerated ChaCha and XChaCha stream ciphers,
+ * including ChaCha20 (RFC7539)
+ *
+ * Copyright (C) 2016-2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2015 Martin Willi
+ */
+
+#include <crypto/algapi.h>
+#include <crypto/internal/chacha.h>
+#include <crypto/internal/simd.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/cputype.h>
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+
+asmlinkage void chacha_block_xor_neon(const u32 *state, u8 *dst, const u8 *src,
+ int nrounds);
+asmlinkage void chacha_4block_xor_neon(const u32 *state, u8 *dst, const u8 *src,
+ int nrounds);
+asmlinkage void hchacha_block_arm(const u32 *state, u32 *out, int nrounds);
+asmlinkage void hchacha_block_neon(const u32 *state, u32 *out, int nrounds);
+
+asmlinkage void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes,
+ const u32 *state, int nrounds);
+
+static inline bool neon_usable(void)
+{
+ return crypto_simd_usable();
+}
+
+static void chacha_doneon(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes, int nrounds)
+{
+ u8 buf[CHACHA_BLOCK_SIZE];
+
+ while (bytes >= CHACHA_BLOCK_SIZE * 4) {
+ chacha_4block_xor_neon(state, dst, src, nrounds);
+ bytes -= CHACHA_BLOCK_SIZE * 4;
+ src += CHACHA_BLOCK_SIZE * 4;
+ dst += CHACHA_BLOCK_SIZE * 4;
+ state[12] += 4;
+ }
+ while (bytes >= CHACHA_BLOCK_SIZE) {
+ chacha_block_xor_neon(state, dst, src, nrounds);
+ bytes -= CHACHA_BLOCK_SIZE;
+ src += CHACHA_BLOCK_SIZE;
+ dst += CHACHA_BLOCK_SIZE;
+ state[12]++;
+ }
+ if (bytes) {
+ memcpy(buf, src, bytes);
+ chacha_block_xor_neon(state, buf, buf, nrounds);
+ memcpy(dst, buf, bytes);
+ }
+}
+
+static int chacha_stream_xor(struct skcipher_request *req,
+ const struct chacha_ctx *ctx, const u8 *iv,
+ bool neon)
+{
+ struct skcipher_walk walk;
+ u32 state[16];
+ int err;
+
+ err = skcipher_walk_virt(&walk, req, false);
+
+ chacha_init_generic(state, ctx->key, iv);
+
+ while (walk.nbytes > 0) {
+ unsigned int nbytes = walk.nbytes;
+
+ if (nbytes < walk.total)
+ nbytes = round_down(nbytes, walk.stride);
+
+ if (!neon) {
+ chacha_doarm(walk.dst.virt.addr, walk.src.virt.addr,
+ nbytes, state, ctx->nrounds);
+ state[12] += DIV_ROUND_UP(nbytes, CHACHA_BLOCK_SIZE);
+ } else {
+ kernel_neon_begin();
+ chacha_doneon(state, walk.dst.virt.addr,
+ walk.src.virt.addr, nbytes, ctx->nrounds);
+ kernel_neon_end();
+ }
+ err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
+ }
+
+ return err;
+}
+
+static int do_chacha(struct skcipher_request *req, bool neon)
+{
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+ return chacha_stream_xor(req, ctx, req->iv, neon);
+}
+
+static int chacha_arm(struct skcipher_request *req)
+{
+ return do_chacha(req, false);
+}
+
+static int chacha_neon(struct skcipher_request *req)
+{
+ return do_chacha(req, neon_usable());
+}
+
+static int do_xchacha(struct skcipher_request *req, bool neon)
+{
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
+ struct chacha_ctx subctx;
+ u32 state[16];
+ u8 real_iv[16];
+
+ chacha_init_generic(state, ctx->key, req->iv);
+
+ if (!neon) {
+ hchacha_block_arm(state, subctx.key, ctx->nrounds);
+ } else {
+ kernel_neon_begin();
+ hchacha_block_neon(state, subctx.key, ctx->nrounds);
+ kernel_neon_end();
+ }
+ subctx.nrounds = ctx->nrounds;
+
+ memcpy(&real_iv[0], req->iv + 24, 8);
+ memcpy(&real_iv[8], req->iv + 16, 8);
+ return chacha_stream_xor(req, &subctx, real_iv, neon);
+}
+
+static int xchacha_arm(struct skcipher_request *req)
+{
+ return do_xchacha(req, false);
+}
+
+static int xchacha_neon(struct skcipher_request *req)
+{
+ return do_xchacha(req, neon_usable());
+}
+
+static struct skcipher_alg arm_algs[] = {
+ {
+ .base.cra_name = "chacha20",
+ .base.cra_driver_name = "chacha20-arm",
+ .base.cra_priority = 200,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = CHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .setkey = chacha20_setkey,
+ .encrypt = chacha_arm,
+ .decrypt = chacha_arm,
+ }, {
+ .base.cra_name = "xchacha20",
+ .base.cra_driver_name = "xchacha20-arm",
+ .base.cra_priority = 200,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = XCHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .setkey = chacha20_setkey,
+ .encrypt = xchacha_arm,
+ .decrypt = xchacha_arm,
+ }, {
+ .base.cra_name = "xchacha12",
+ .base.cra_driver_name = "xchacha12-arm",
+ .base.cra_priority = 200,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = XCHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .setkey = chacha12_setkey,
+ .encrypt = xchacha_arm,
+ .decrypt = xchacha_arm,
+ },
+};
+
+static struct skcipher_alg neon_algs[] = {
+ {
+ .base.cra_name = "chacha20",
+ .base.cra_driver_name = "chacha20-neon",
+ .base.cra_priority = 300,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = CHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .walksize = 4 * CHACHA_BLOCK_SIZE,
+ .setkey = chacha20_setkey,
+ .encrypt = chacha_neon,
+ .decrypt = chacha_neon,
+ }, {
+ .base.cra_name = "xchacha20",
+ .base.cra_driver_name = "xchacha20-neon",
+ .base.cra_priority = 300,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = XCHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .walksize = 4 * CHACHA_BLOCK_SIZE,
+ .setkey = chacha20_setkey,
+ .encrypt = xchacha_neon,
+ .decrypt = xchacha_neon,
+ }, {
+ .base.cra_name = "xchacha12",
+ .base.cra_driver_name = "xchacha12-neon",
+ .base.cra_priority = 300,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = XCHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .walksize = 4 * CHACHA_BLOCK_SIZE,
+ .setkey = chacha12_setkey,
+ .encrypt = xchacha_neon,
+ .decrypt = xchacha_neon,
+ }
+};
+
+static int __init chacha_simd_mod_init(void)
+{
+ int err;
+
+ err = crypto_register_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
+ if (err)
+ return err;
+
+ if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON)) {
+ int i;
+
+ switch (read_cpuid_part()) {
+ case ARM_CPU_PART_CORTEX_A7:
+ case ARM_CPU_PART_CORTEX_A5:
+ /*
+ * The Cortex-A7 and Cortex-A5 do not perform well with
+ * the NEON implementation but do incredibly with the
+ * scalar one and use less power.
+ */
+ for (i = 0; i < ARRAY_SIZE(neon_algs); i++)
+ neon_algs[i].base.cra_priority = 0;
+ break;
+ }
+
+ err = crypto_register_skciphers(neon_algs, ARRAY_SIZE(neon_algs));
+ if (err)
+ crypto_unregister_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
+ }
+ return err;
+}
+
+static void __exit chacha_simd_mod_fini(void)
+{
+ crypto_unregister_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
+ if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON))
+ crypto_unregister_skciphers(neon_algs, ARRAY_SIZE(neon_algs));
+}
+
+module_init(chacha_simd_mod_init);
+module_exit(chacha_simd_mod_fini);
+
+MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (scalar and NEON accelerated)");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("chacha20");
+MODULE_ALIAS_CRYPTO("chacha20-arm");
+MODULE_ALIAS_CRYPTO("xchacha20");
+MODULE_ALIAS_CRYPTO("xchacha20-arm");
+MODULE_ALIAS_CRYPTO("xchacha12");
+MODULE_ALIAS_CRYPTO("xchacha12-arm");
+#ifdef CONFIG_KERNEL_MODE_NEON
+MODULE_ALIAS_CRYPTO("chacha20-neon");
+MODULE_ALIAS_CRYPTO("xchacha20-neon");
+MODULE_ALIAS_CRYPTO("xchacha12-neon");
+#endif
--- a/arch/arm/crypto/chacha-neon-glue.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * ARM NEON accelerated ChaCha and XChaCha stream ciphers,
- * including ChaCha20 (RFC7539)
- *
- * Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Based on:
- * ChaCha20 256-bit cipher algorithm, RFC7539, SIMD glue code
- *
- * Copyright (C) 2015 Martin Willi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <crypto/algapi.h>
-#include <crypto/internal/chacha.h>
-#include <crypto/internal/simd.h>
-#include <crypto/internal/skcipher.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <asm/hwcap.h>
-#include <asm/neon.h>
-#include <asm/simd.h>
-
-asmlinkage void chacha_block_xor_neon(const u32 *state, u8 *dst, const u8 *src,
- int nrounds);
-asmlinkage void chacha_4block_xor_neon(const u32 *state, u8 *dst, const u8 *src,
- int nrounds);
-asmlinkage void hchacha_block_neon(const u32 *state, u32 *out, int nrounds);
-
-static void chacha_doneon(u32 *state, u8 *dst, const u8 *src,
- unsigned int bytes, int nrounds)
-{
- u8 buf[CHACHA_BLOCK_SIZE];
-
- while (bytes >= CHACHA_BLOCK_SIZE * 4) {
- chacha_4block_xor_neon(state, dst, src, nrounds);
- bytes -= CHACHA_BLOCK_SIZE * 4;
- src += CHACHA_BLOCK_SIZE * 4;
- dst += CHACHA_BLOCK_SIZE * 4;
- state[12] += 4;
- }
- while (bytes >= CHACHA_BLOCK_SIZE) {
- chacha_block_xor_neon(state, dst, src, nrounds);
- bytes -= CHACHA_BLOCK_SIZE;
- src += CHACHA_BLOCK_SIZE;
- dst += CHACHA_BLOCK_SIZE;
- state[12]++;
- }
- if (bytes) {
- memcpy(buf, src, bytes);
- chacha_block_xor_neon(state, buf, buf, nrounds);
- memcpy(dst, buf, bytes);
- }
-}
-
-static int chacha_neon_stream_xor(struct skcipher_request *req,
- const struct chacha_ctx *ctx, const u8 *iv)
-{
- struct skcipher_walk walk;
- u32 state[16];
- int err;
-
- err = skcipher_walk_virt(&walk, req, false);
-
- crypto_chacha_init(state, ctx, iv);
-
- while (walk.nbytes > 0) {
- unsigned int nbytes = walk.nbytes;
-
- if (nbytes < walk.total)
- nbytes = round_down(nbytes, walk.stride);
-
- kernel_neon_begin();
- chacha_doneon(state, walk.dst.virt.addr, walk.src.virt.addr,
- nbytes, ctx->nrounds);
- kernel_neon_end();
- err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
- }
-
- return err;
-}
-
-static int chacha_neon(struct skcipher_request *req)
-{
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
-
- if (req->cryptlen <= CHACHA_BLOCK_SIZE || !crypto_simd_usable())
- return crypto_chacha_crypt(req);
-
- return chacha_neon_stream_xor(req, ctx, req->iv);
-}
-
-static int xchacha_neon(struct skcipher_request *req)
-{
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
- struct chacha_ctx subctx;
- u32 state[16];
- u8 real_iv[16];
-
- if (req->cryptlen <= CHACHA_BLOCK_SIZE || !crypto_simd_usable())
- return crypto_xchacha_crypt(req);
-
- crypto_chacha_init(state, ctx, req->iv);
-
- kernel_neon_begin();
- hchacha_block_neon(state, subctx.key, ctx->nrounds);
- kernel_neon_end();
- subctx.nrounds = ctx->nrounds;
-
- memcpy(&real_iv[0], req->iv + 24, 8);
- memcpy(&real_iv[8], req->iv + 16, 8);
- return chacha_neon_stream_xor(req, &subctx, real_iv);
-}
-
-static struct skcipher_alg algs[] = {
- {
- .base.cra_name = "chacha20",
- .base.cra_driver_name = "chacha20-neon",
- .base.cra_priority = 300,
- .base.cra_blocksize = 1,
- .base.cra_ctxsize = sizeof(struct chacha_ctx),
- .base.cra_module = THIS_MODULE,
-
- .min_keysize = CHACHA_KEY_SIZE,
- .max_keysize = CHACHA_KEY_SIZE,
- .ivsize = CHACHA_IV_SIZE,
- .chunksize = CHACHA_BLOCK_SIZE,
- .walksize = 4 * CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha20_setkey,
- .encrypt = chacha_neon,
- .decrypt = chacha_neon,
- }, {
- .base.cra_name = "xchacha20",
- .base.cra_driver_name = "xchacha20-neon",
- .base.cra_priority = 300,
- .base.cra_blocksize = 1,
- .base.cra_ctxsize = sizeof(struct chacha_ctx),
- .base.cra_module = THIS_MODULE,
-
- .min_keysize = CHACHA_KEY_SIZE,
- .max_keysize = CHACHA_KEY_SIZE,
- .ivsize = XCHACHA_IV_SIZE,
- .chunksize = CHACHA_BLOCK_SIZE,
- .walksize = 4 * CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha20_setkey,
- .encrypt = xchacha_neon,
- .decrypt = xchacha_neon,
- }, {
- .base.cra_name = "xchacha12",
- .base.cra_driver_name = "xchacha12-neon",
- .base.cra_priority = 300,
- .base.cra_blocksize = 1,
- .base.cra_ctxsize = sizeof(struct chacha_ctx),
- .base.cra_module = THIS_MODULE,
-
- .min_keysize = CHACHA_KEY_SIZE,
- .max_keysize = CHACHA_KEY_SIZE,
- .ivsize = XCHACHA_IV_SIZE,
- .chunksize = CHACHA_BLOCK_SIZE,
- .walksize = 4 * CHACHA_BLOCK_SIZE,
- .setkey = crypto_chacha12_setkey,
- .encrypt = xchacha_neon,
- .decrypt = xchacha_neon,
- }
-};
-
-static int __init chacha_simd_mod_init(void)
-{
- if (!(elf_hwcap & HWCAP_NEON))
- return -ENODEV;
-
- return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
-}
-
-static void __exit chacha_simd_mod_fini(void)
-{
- crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
-}
-
-module_init(chacha_simd_mod_init);
-module_exit(chacha_simd_mod_fini);
-
-MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (NEON accelerated)");
-MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS_CRYPTO("chacha20");
-MODULE_ALIAS_CRYPTO("chacha20-neon");
-MODULE_ALIAS_CRYPTO("xchacha20");
-MODULE_ALIAS_CRYPTO("xchacha20-neon");
-MODULE_ALIAS_CRYPTO("xchacha12");
-MODULE_ALIAS_CRYPTO("xchacha12-neon");
--- a/arch/arm/crypto/chacha-scalar-core.S
+++ b/arch/arm/crypto/chacha-scalar-core.S
@@ -41,14 +41,6 @@
X14 .req r12
X15 .req r14
-.Lexpand_32byte_k:
- // "expand 32-byte k"
- .word 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
-
-#ifdef __thumb2__
-# define adrl adr
-#endif
-
.macro __rev out, in, t0, t1, t2
.if __LINUX_ARM_ARCH__ >= 6
rev \out, \in
@@ -391,61 +383,65 @@
.endm // _chacha
/*
- * void chacha20_arm(u8 *out, const u8 *in, size_t len, const u32 key[8],
- * const u32 iv[4]);
+ * void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes,
+ * const u32 *state, int nrounds);
*/
-ENTRY(chacha20_arm)
+ENTRY(chacha_doarm)
cmp r2, #0 // len == 0?
reteq lr
+ ldr ip, [sp]
+ cmp ip, #12
+
push {r0-r2,r4-r11,lr}
// Push state x0-x15 onto stack.
// Also store an extra copy of x10-x11 just before the state.
- ldr r4, [sp, #48] // iv
- mov r0, sp
- sub sp, #80
-
- // iv: x12-x15
- ldm r4, {X12,X13,X14,X15}
- stmdb r0!, {X12,X13,X14,X15}
+ add X12, r3, #48
+ ldm X12, {X12,X13,X14,X15}
+ push {X12,X13,X14,X15}
+ sub sp, sp, #64
- // key: x4-x11
- __ldrd X8_X10, X9_X11, r3, 24
+ __ldrd X8_X10, X9_X11, r3, 40
__strd X8_X10, X9_X11, sp, 8
- stmdb r0!, {X8_X10, X9_X11}
- ldm r3, {X4-X9_X11}
- stmdb r0!, {X4-X9_X11}
-
- // constants: x0-x3
- adrl X3, .Lexpand_32byte_k
- ldm X3, {X0-X3}
+ __strd X8_X10, X9_X11, sp, 56
+ ldm r3, {X0-X9_X11}
__strd X0, X1, sp, 16
__strd X2, X3, sp, 24
+ __strd X4, X5, sp, 32
+ __strd X6, X7, sp, 40
+ __strd X8_X10, X9_X11, sp, 48
+ beq 1f
_chacha 20
- add sp, #76
+0: add sp, #76
pop {r4-r11, pc}
-ENDPROC(chacha20_arm)
+
+1: _chacha 12
+ b 0b
+ENDPROC(chacha_doarm)
/*
- * void hchacha20_arm(const u32 state[16], u32 out[8]);
+ * void hchacha_block_arm(const u32 state[16], u32 out[8], int nrounds);
*/
-ENTRY(hchacha20_arm)
+ENTRY(hchacha_block_arm)
push {r1,r4-r11,lr}
+ cmp r2, #12 // ChaCha12 ?
+
mov r14, r0
ldmia r14!, {r0-r11} // load x0-x11
push {r10-r11} // store x10-x11 to stack
ldm r14, {r10-r12,r14} // load x12-x15
sub sp, #8
+ beq 1f
_chacha_permute 20
// Skip over (unused0-unused1, x10-x11)
- add sp, #16
+0: add sp, #16
// Fix up rotations of x12-x15
ror X12, X12, #drot
@@ -458,4 +454,7 @@ ENTRY(hchacha20_arm)
stm r4, {X0,X1,X2,X3,X12,X13,X14,X15}
pop {r4-r11,pc}
-ENDPROC(hchacha20_arm)
+
+1: _chacha_permute 12
+ b 0b
+ENDPROC(hchacha_block_arm)
--- a/arch/arm64/crypto/chacha-neon-glue.c
+++ b/arch/arm64/crypto/chacha-neon-glue.c
@@ -1,5 +1,5 @@
/*
- * ARM NEON accelerated ChaCha and XChaCha stream ciphers,
+ * ARM NEON and scalar accelerated ChaCha and XChaCha stream ciphers,
* including ChaCha20 (RFC7539)
*
* Copyright (C) 2016 - 2017 Linaro, Ltd. <ard.biesheuvel@linaro.org>

View File

@@ -1,108 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:15 +0100
Subject: [PATCH] crypto: arm/chacha - expose ARM ChaCha routine as library
function
commit a44a3430d71bad4ee56788a59fff099b291ea54c upstream.
Expose the accelerated NEON ChaCha routine directly as a symbol
export so that users of the ChaCha library API can use it directly.
Given that calls into the library API will always go through the
routines in this module if it is enabled, switch to static keys
to select the optimal implementation available (which may be none
at all, in which case we defer to the generic implementation for
all invocations).
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/arm/crypto/Kconfig | 1 +
arch/arm/crypto/chacha-glue.c | 41 ++++++++++++++++++++++++++++++++++-
2 files changed, 41 insertions(+), 1 deletion(-)
--- a/arch/arm/crypto/Kconfig
+++ b/arch/arm/crypto/Kconfig
@@ -129,6 +129,7 @@ config CRYPTO_CRC32_ARM_CE
config CRYPTO_CHACHA20_NEON
tristate "NEON and scalar accelerated ChaCha stream cipher algorithms"
select CRYPTO_BLKCIPHER
+ select CRYPTO_ARCH_HAVE_LIB_CHACHA
config CRYPTO_NHPOLY1305_NEON
tristate "NEON accelerated NHPoly1305 hash function (for Adiantum)"
--- a/arch/arm/crypto/chacha-glue.c
+++ b/arch/arm/crypto/chacha-glue.c
@@ -11,6 +11,7 @@
#include <crypto/internal/chacha.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
+#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -29,9 +30,11 @@ asmlinkage void hchacha_block_neon(const
asmlinkage void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes,
const u32 *state, int nrounds);
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(use_neon);
+
static inline bool neon_usable(void)
{
- return crypto_simd_usable();
+ return static_branch_likely(&use_neon) && crypto_simd_usable();
}
static void chacha_doneon(u32 *state, u8 *dst, const u8 *src,
@@ -60,6 +63,40 @@ static void chacha_doneon(u32 *state, u8
}
}
+void hchacha_block_arch(const u32 *state, u32 *stream, int nrounds)
+{
+ if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon_usable()) {
+ hchacha_block_arm(state, stream, nrounds);
+ } else {
+ kernel_neon_begin();
+ hchacha_block_neon(state, stream, nrounds);
+ kernel_neon_end();
+ }
+}
+EXPORT_SYMBOL(hchacha_block_arch);
+
+void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv)
+{
+ chacha_init_generic(state, key, iv);
+}
+EXPORT_SYMBOL(chacha_init_arch);
+
+void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
+ int nrounds)
+{
+ if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon_usable() ||
+ bytes <= CHACHA_BLOCK_SIZE) {
+ chacha_doarm(dst, src, bytes, state, nrounds);
+ state[12] += DIV_ROUND_UP(bytes, CHACHA_BLOCK_SIZE);
+ return;
+ }
+
+ kernel_neon_begin();
+ chacha_doneon(state, dst, src, bytes, nrounds);
+ kernel_neon_end();
+}
+EXPORT_SYMBOL(chacha_crypt_arch);
+
static int chacha_stream_xor(struct skcipher_request *req,
const struct chacha_ctx *ctx, const u8 *iv,
bool neon)
@@ -269,6 +306,8 @@ static int __init chacha_simd_mod_init(v
for (i = 0; i < ARRAY_SIZE(neon_algs); i++)
neon_algs[i].base.cra_priority = 0;
break;
+ default:
+ static_branch_enable(&use_neon);
}
err = crypto_register_skciphers(neon_algs, ARRAY_SIZE(neon_algs));

View File

@@ -1,451 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Fri, 8 Nov 2019 13:22:16 +0100
Subject: [PATCH] crypto: mips/chacha - import 32r2 ChaCha code from Zinc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
commit 49aa7c00eddf8d8f462b0256bd82e81762d7b0c6 upstream.
This imports the accelerated MIPS 32r2 ChaCha20 implementation from the
Zinc patch set.
Co-developed-by: René van Dorst <opensource@vdorst.com>
Signed-off-by: René van Dorst <opensource@vdorst.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/mips/crypto/chacha-core.S | 424 +++++++++++++++++++++++++++++++++
1 file changed, 424 insertions(+)
create mode 100644 arch/mips/crypto/chacha-core.S
--- /dev/null
+++ b/arch/mips/crypto/chacha-core.S
@@ -0,0 +1,424 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2016-2018 René van Dorst <opensource@vdorst.com>. All Rights Reserved.
+ * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+#define MASK_U32 0x3c
+#define CHACHA20_BLOCK_SIZE 64
+#define STACK_SIZE 32
+
+#define X0 $t0
+#define X1 $t1
+#define X2 $t2
+#define X3 $t3
+#define X4 $t4
+#define X5 $t5
+#define X6 $t6
+#define X7 $t7
+#define X8 $t8
+#define X9 $t9
+#define X10 $v1
+#define X11 $s6
+#define X12 $s5
+#define X13 $s4
+#define X14 $s3
+#define X15 $s2
+/* Use regs which are overwritten on exit for Tx so we don't leak clear data. */
+#define T0 $s1
+#define T1 $s0
+#define T(n) T ## n
+#define X(n) X ## n
+
+/* Input arguments */
+#define STATE $a0
+#define OUT $a1
+#define IN $a2
+#define BYTES $a3
+
+/* Output argument */
+/* NONCE[0] is kept in a register and not in memory.
+ * We don't want to touch original value in memory.
+ * Must be incremented every loop iteration.
+ */
+#define NONCE_0 $v0
+
+/* SAVED_X and SAVED_CA are set in the jump table.
+ * Use regs which are overwritten on exit else we don't leak clear data.
+ * They are used to handling the last bytes which are not multiple of 4.
+ */
+#define SAVED_X X15
+#define SAVED_CA $s7
+
+#define IS_UNALIGNED $s7
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define MSB 0
+#define LSB 3
+#define ROTx rotl
+#define ROTR(n) rotr n, 24
+#define CPU_TO_LE32(n) \
+ wsbh n; \
+ rotr n, 16;
+#else
+#define MSB 3
+#define LSB 0
+#define ROTx rotr
+#define CPU_TO_LE32(n)
+#define ROTR(n)
+#endif
+
+#define FOR_EACH_WORD(x) \
+ x( 0); \
+ x( 1); \
+ x( 2); \
+ x( 3); \
+ x( 4); \
+ x( 5); \
+ x( 6); \
+ x( 7); \
+ x( 8); \
+ x( 9); \
+ x(10); \
+ x(11); \
+ x(12); \
+ x(13); \
+ x(14); \
+ x(15);
+
+#define FOR_EACH_WORD_REV(x) \
+ x(15); \
+ x(14); \
+ x(13); \
+ x(12); \
+ x(11); \
+ x(10); \
+ x( 9); \
+ x( 8); \
+ x( 7); \
+ x( 6); \
+ x( 5); \
+ x( 4); \
+ x( 3); \
+ x( 2); \
+ x( 1); \
+ x( 0);
+
+#define PLUS_ONE_0 1
+#define PLUS_ONE_1 2
+#define PLUS_ONE_2 3
+#define PLUS_ONE_3 4
+#define PLUS_ONE_4 5
+#define PLUS_ONE_5 6
+#define PLUS_ONE_6 7
+#define PLUS_ONE_7 8
+#define PLUS_ONE_8 9
+#define PLUS_ONE_9 10
+#define PLUS_ONE_10 11
+#define PLUS_ONE_11 12
+#define PLUS_ONE_12 13
+#define PLUS_ONE_13 14
+#define PLUS_ONE_14 15
+#define PLUS_ONE_15 16
+#define PLUS_ONE(x) PLUS_ONE_ ## x
+#define _CONCAT3(a,b,c) a ## b ## c
+#define CONCAT3(a,b,c) _CONCAT3(a,b,c)
+
+#define STORE_UNALIGNED(x) \
+CONCAT3(.Lchacha20_mips_xor_unaligned_, PLUS_ONE(x), _b: ;) \
+ .if (x != 12); \
+ lw T0, (x*4)(STATE); \
+ .endif; \
+ lwl T1, (x*4)+MSB ## (IN); \
+ lwr T1, (x*4)+LSB ## (IN); \
+ .if (x == 12); \
+ addu X ## x, NONCE_0; \
+ .else; \
+ addu X ## x, T0; \
+ .endif; \
+ CPU_TO_LE32(X ## x); \
+ xor X ## x, T1; \
+ swl X ## x, (x*4)+MSB ## (OUT); \
+ swr X ## x, (x*4)+LSB ## (OUT);
+
+#define STORE_ALIGNED(x) \
+CONCAT3(.Lchacha20_mips_xor_aligned_, PLUS_ONE(x), _b: ;) \
+ .if (x != 12); \
+ lw T0, (x*4)(STATE); \
+ .endif; \
+ lw T1, (x*4) ## (IN); \
+ .if (x == 12); \
+ addu X ## x, NONCE_0; \
+ .else; \
+ addu X ## x, T0; \
+ .endif; \
+ CPU_TO_LE32(X ## x); \
+ xor X ## x, T1; \
+ sw X ## x, (x*4) ## (OUT);
+
+/* Jump table macro.
+ * Used for setup and handling the last bytes, which are not multiple of 4.
+ * X15 is free to store Xn
+ * Every jumptable entry must be equal in size.
+ */
+#define JMPTBL_ALIGNED(x) \
+.Lchacha20_mips_jmptbl_aligned_ ## x: ; \
+ .set noreorder; \
+ b .Lchacha20_mips_xor_aligned_ ## x ## _b; \
+ .if (x == 12); \
+ addu SAVED_X, X ## x, NONCE_0; \
+ .else; \
+ addu SAVED_X, X ## x, SAVED_CA; \
+ .endif; \
+ .set reorder
+
+#define JMPTBL_UNALIGNED(x) \
+.Lchacha20_mips_jmptbl_unaligned_ ## x: ; \
+ .set noreorder; \
+ b .Lchacha20_mips_xor_unaligned_ ## x ## _b; \
+ .if (x == 12); \
+ addu SAVED_X, X ## x, NONCE_0; \
+ .else; \
+ addu SAVED_X, X ## x, SAVED_CA; \
+ .endif; \
+ .set reorder
+
+#define AXR(A, B, C, D, K, L, M, N, V, W, Y, Z, S) \
+ addu X(A), X(K); \
+ addu X(B), X(L); \
+ addu X(C), X(M); \
+ addu X(D), X(N); \
+ xor X(V), X(A); \
+ xor X(W), X(B); \
+ xor X(Y), X(C); \
+ xor X(Z), X(D); \
+ rotl X(V), S; \
+ rotl X(W), S; \
+ rotl X(Y), S; \
+ rotl X(Z), S;
+
+.text
+.set reorder
+.set noat
+.globl chacha20_mips
+.ent chacha20_mips
+chacha20_mips:
+ .frame $sp, STACK_SIZE, $ra
+
+ addiu $sp, -STACK_SIZE
+
+ /* Return bytes = 0. */
+ beqz BYTES, .Lchacha20_mips_end
+
+ lw NONCE_0, 48(STATE)
+
+ /* Save s0-s7 */
+ sw $s0, 0($sp)
+ sw $s1, 4($sp)
+ sw $s2, 8($sp)
+ sw $s3, 12($sp)
+ sw $s4, 16($sp)
+ sw $s5, 20($sp)
+ sw $s6, 24($sp)
+ sw $s7, 28($sp)
+
+ /* Test IN or OUT is unaligned.
+ * IS_UNALIGNED = ( IN | OUT ) & 0x00000003
+ */
+ or IS_UNALIGNED, IN, OUT
+ andi IS_UNALIGNED, 0x3
+
+ /* Set number of rounds */
+ li $at, 20
+
+ b .Lchacha20_rounds_start
+
+.align 4
+.Loop_chacha20_rounds:
+ addiu IN, CHACHA20_BLOCK_SIZE
+ addiu OUT, CHACHA20_BLOCK_SIZE
+ addiu NONCE_0, 1
+
+.Lchacha20_rounds_start:
+ lw X0, 0(STATE)
+ lw X1, 4(STATE)
+ lw X2, 8(STATE)
+ lw X3, 12(STATE)
+
+ lw X4, 16(STATE)
+ lw X5, 20(STATE)
+ lw X6, 24(STATE)
+ lw X7, 28(STATE)
+ lw X8, 32(STATE)
+ lw X9, 36(STATE)
+ lw X10, 40(STATE)
+ lw X11, 44(STATE)
+
+ move X12, NONCE_0
+ lw X13, 52(STATE)
+ lw X14, 56(STATE)
+ lw X15, 60(STATE)
+
+.Loop_chacha20_xor_rounds:
+ addiu $at, -2
+ AXR( 0, 1, 2, 3, 4, 5, 6, 7, 12,13,14,15, 16);
+ AXR( 8, 9,10,11, 12,13,14,15, 4, 5, 6, 7, 12);
+ AXR( 0, 1, 2, 3, 4, 5, 6, 7, 12,13,14,15, 8);
+ AXR( 8, 9,10,11, 12,13,14,15, 4, 5, 6, 7, 7);
+ AXR( 0, 1, 2, 3, 5, 6, 7, 4, 15,12,13,14, 16);
+ AXR(10,11, 8, 9, 15,12,13,14, 5, 6, 7, 4, 12);
+ AXR( 0, 1, 2, 3, 5, 6, 7, 4, 15,12,13,14, 8);
+ AXR(10,11, 8, 9, 15,12,13,14, 5, 6, 7, 4, 7);
+ bnez $at, .Loop_chacha20_xor_rounds
+
+ addiu BYTES, -(CHACHA20_BLOCK_SIZE)
+
+ /* Is data src/dst unaligned? Jump */
+ bnez IS_UNALIGNED, .Loop_chacha20_unaligned
+
+ /* Set number rounds here to fill delayslot. */
+ li $at, 20
+
+ /* BYTES < 0, it has no full block. */
+ bltz BYTES, .Lchacha20_mips_no_full_block_aligned
+
+ FOR_EACH_WORD_REV(STORE_ALIGNED)
+
+ /* BYTES > 0? Loop again. */
+ bgtz BYTES, .Loop_chacha20_rounds
+
+ /* Place this here to fill delay slot */
+ addiu NONCE_0, 1
+
+ /* BYTES < 0? Handle last bytes */
+ bltz BYTES, .Lchacha20_mips_xor_bytes
+
+.Lchacha20_mips_xor_done:
+ /* Restore used registers */
+ lw $s0, 0($sp)
+ lw $s1, 4($sp)
+ lw $s2, 8($sp)
+ lw $s3, 12($sp)
+ lw $s4, 16($sp)
+ lw $s5, 20($sp)
+ lw $s6, 24($sp)
+ lw $s7, 28($sp)
+
+ /* Write NONCE_0 back to right location in state */
+ sw NONCE_0, 48(STATE)
+
+.Lchacha20_mips_end:
+ addiu $sp, STACK_SIZE
+ jr $ra
+
+.Lchacha20_mips_no_full_block_aligned:
+ /* Restore the offset on BYTES */
+ addiu BYTES, CHACHA20_BLOCK_SIZE
+
+ /* Get number of full WORDS */
+ andi $at, BYTES, MASK_U32
+
+ /* Load upper half of jump table addr */
+ lui T0, %hi(.Lchacha20_mips_jmptbl_aligned_0)
+
+ /* Calculate lower half jump table offset */
+ ins T0, $at, 1, 6
+
+ /* Add offset to STATE */
+ addu T1, STATE, $at
+
+ /* Add lower half jump table addr */
+ addiu T0, %lo(.Lchacha20_mips_jmptbl_aligned_0)
+
+ /* Read value from STATE */
+ lw SAVED_CA, 0(T1)
+
+ /* Store remaining bytecounter as negative value */
+ subu BYTES, $at, BYTES
+
+ jr T0
+
+ /* Jump table */
+ FOR_EACH_WORD(JMPTBL_ALIGNED)
+
+
+.Loop_chacha20_unaligned:
+ /* Set number rounds here to fill delayslot. */
+ li $at, 20
+
+ /* BYTES > 0, it has no full block. */
+ bltz BYTES, .Lchacha20_mips_no_full_block_unaligned
+
+ FOR_EACH_WORD_REV(STORE_UNALIGNED)
+
+ /* BYTES > 0? Loop again. */
+ bgtz BYTES, .Loop_chacha20_rounds
+
+ /* Write NONCE_0 back to right location in state */
+ sw NONCE_0, 48(STATE)
+
+ .set noreorder
+ /* Fall through to byte handling */
+ bgez BYTES, .Lchacha20_mips_xor_done
+.Lchacha20_mips_xor_unaligned_0_b:
+.Lchacha20_mips_xor_aligned_0_b:
+ /* Place this here to fill delay slot */
+ addiu NONCE_0, 1
+ .set reorder
+
+.Lchacha20_mips_xor_bytes:
+ addu IN, $at
+ addu OUT, $at
+ /* First byte */
+ lbu T1, 0(IN)
+ addiu $at, BYTES, 1
+ CPU_TO_LE32(SAVED_X)
+ ROTR(SAVED_X)
+ xor T1, SAVED_X
+ sb T1, 0(OUT)
+ beqz $at, .Lchacha20_mips_xor_done
+ /* Second byte */
+ lbu T1, 1(IN)
+ addiu $at, BYTES, 2
+ ROTx SAVED_X, 8
+ xor T1, SAVED_X
+ sb T1, 1(OUT)
+ beqz $at, .Lchacha20_mips_xor_done
+ /* Third byte */
+ lbu T1, 2(IN)
+ ROTx SAVED_X, 8
+ xor T1, SAVED_X
+ sb T1, 2(OUT)
+ b .Lchacha20_mips_xor_done
+
+.Lchacha20_mips_no_full_block_unaligned:
+ /* Restore the offset on BYTES */
+ addiu BYTES, CHACHA20_BLOCK_SIZE
+
+ /* Get number of full WORDS */
+ andi $at, BYTES, MASK_U32
+
+ /* Load upper half of jump table addr */
+ lui T0, %hi(.Lchacha20_mips_jmptbl_unaligned_0)
+
+ /* Calculate lower half jump table offset */
+ ins T0, $at, 1, 6
+
+ /* Add offset to STATE */
+ addu T1, STATE, $at
+
+ /* Add lower half jump table addr */
+ addiu T0, %lo(.Lchacha20_mips_jmptbl_unaligned_0)
+
+ /* Read value from STATE */
+ lw SAVED_CA, 0(T1)
+
+ /* Store remaining bytecounter as negative value */
+ subu BYTES, $at, BYTES
+
+ jr T0
+
+ /* Jump table */
+ FOR_EACH_WORD(JMPTBL_UNALIGNED)
+.end chacha20_mips
+.set at

View File

@@ -1,559 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:17 +0100
Subject: [PATCH] crypto: mips/chacha - wire up accelerated 32r2 code from Zinc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
commit 3a2f58f3ba4f6f44e33d1a48240d5eadb882cb59 upstream.
This integrates the accelerated MIPS 32r2 implementation of ChaCha
into both the API and library interfaces of the kernel crypto stack.
The significance of this is that, in addition to becoming available
as an accelerated library implementation, it can also be used by
existing crypto API code such as Adiantum (for block encryption on
ultra low performance cores) or IPsec using chacha20poly1305. These
are use cases that have already opted into using the abstract crypto
API. In order to support Adiantum, the core assembler routine has
been adapted to take the round count as a function argument rather
than hardcoding it to 20.
Co-developed-by: René van Dorst <opensource@vdorst.com>
Signed-off-by: René van Dorst <opensource@vdorst.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/mips/Makefile | 2 +-
arch/mips/crypto/Makefile | 4 +
arch/mips/crypto/chacha-core.S | 159 ++++++++++++++++++++++++---------
arch/mips/crypto/chacha-glue.c | 150 +++++++++++++++++++++++++++++++
crypto/Kconfig | 6 ++
5 files changed, 277 insertions(+), 44 deletions(-)
create mode 100644 arch/mips/crypto/chacha-glue.c
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -334,7 +334,7 @@ libs-$(CONFIG_MIPS_FP_SUPPORT) += arch/m
# See arch/mips/Kbuild for content of core part of the kernel
core-y += arch/mips/
-drivers-$(CONFIG_MIPS_CRC_SUPPORT) += arch/mips/crypto/
+drivers-y += arch/mips/crypto/
drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/
# suspend and hibernation support
--- a/arch/mips/crypto/Makefile
+++ b/arch/mips/crypto/Makefile
@@ -4,3 +4,7 @@
#
obj-$(CONFIG_CRYPTO_CRC32_MIPS) += crc32-mips.o
+
+obj-$(CONFIG_CRYPTO_CHACHA_MIPS) += chacha-mips.o
+chacha-mips-y := chacha-core.o chacha-glue.o
+AFLAGS_chacha-core.o += -O2 # needed to fill branch delay slots
--- a/arch/mips/crypto/chacha-core.S
+++ b/arch/mips/crypto/chacha-core.S
@@ -125,7 +125,7 @@
#define CONCAT3(a,b,c) _CONCAT3(a,b,c)
#define STORE_UNALIGNED(x) \
-CONCAT3(.Lchacha20_mips_xor_unaligned_, PLUS_ONE(x), _b: ;) \
+CONCAT3(.Lchacha_mips_xor_unaligned_, PLUS_ONE(x), _b: ;) \
.if (x != 12); \
lw T0, (x*4)(STATE); \
.endif; \
@@ -142,7 +142,7 @@ CONCAT3(.Lchacha20_mips_xor_unaligned_,
swr X ## x, (x*4)+LSB ## (OUT);
#define STORE_ALIGNED(x) \
-CONCAT3(.Lchacha20_mips_xor_aligned_, PLUS_ONE(x), _b: ;) \
+CONCAT3(.Lchacha_mips_xor_aligned_, PLUS_ONE(x), _b: ;) \
.if (x != 12); \
lw T0, (x*4)(STATE); \
.endif; \
@@ -162,9 +162,9 @@ CONCAT3(.Lchacha20_mips_xor_aligned_, PL
* Every jumptable entry must be equal in size.
*/
#define JMPTBL_ALIGNED(x) \
-.Lchacha20_mips_jmptbl_aligned_ ## x: ; \
+.Lchacha_mips_jmptbl_aligned_ ## x: ; \
.set noreorder; \
- b .Lchacha20_mips_xor_aligned_ ## x ## _b; \
+ b .Lchacha_mips_xor_aligned_ ## x ## _b; \
.if (x == 12); \
addu SAVED_X, X ## x, NONCE_0; \
.else; \
@@ -173,9 +173,9 @@ CONCAT3(.Lchacha20_mips_xor_aligned_, PL
.set reorder
#define JMPTBL_UNALIGNED(x) \
-.Lchacha20_mips_jmptbl_unaligned_ ## x: ; \
+.Lchacha_mips_jmptbl_unaligned_ ## x: ; \
.set noreorder; \
- b .Lchacha20_mips_xor_unaligned_ ## x ## _b; \
+ b .Lchacha_mips_xor_unaligned_ ## x ## _b; \
.if (x == 12); \
addu SAVED_X, X ## x, NONCE_0; \
.else; \
@@ -200,15 +200,18 @@ CONCAT3(.Lchacha20_mips_xor_aligned_, PL
.text
.set reorder
.set noat
-.globl chacha20_mips
-.ent chacha20_mips
-chacha20_mips:
+.globl chacha_crypt_arch
+.ent chacha_crypt_arch
+chacha_crypt_arch:
.frame $sp, STACK_SIZE, $ra
+ /* Load number of rounds */
+ lw $at, 16($sp)
+
addiu $sp, -STACK_SIZE
/* Return bytes = 0. */
- beqz BYTES, .Lchacha20_mips_end
+ beqz BYTES, .Lchacha_mips_end
lw NONCE_0, 48(STATE)
@@ -228,18 +231,15 @@ chacha20_mips:
or IS_UNALIGNED, IN, OUT
andi IS_UNALIGNED, 0x3
- /* Set number of rounds */
- li $at, 20
-
- b .Lchacha20_rounds_start
+ b .Lchacha_rounds_start
.align 4
-.Loop_chacha20_rounds:
+.Loop_chacha_rounds:
addiu IN, CHACHA20_BLOCK_SIZE
addiu OUT, CHACHA20_BLOCK_SIZE
addiu NONCE_0, 1
-.Lchacha20_rounds_start:
+.Lchacha_rounds_start:
lw X0, 0(STATE)
lw X1, 4(STATE)
lw X2, 8(STATE)
@@ -259,7 +259,7 @@ chacha20_mips:
lw X14, 56(STATE)
lw X15, 60(STATE)
-.Loop_chacha20_xor_rounds:
+.Loop_chacha_xor_rounds:
addiu $at, -2
AXR( 0, 1, 2, 3, 4, 5, 6, 7, 12,13,14,15, 16);
AXR( 8, 9,10,11, 12,13,14,15, 4, 5, 6, 7, 12);
@@ -269,31 +269,31 @@ chacha20_mips:
AXR(10,11, 8, 9, 15,12,13,14, 5, 6, 7, 4, 12);
AXR( 0, 1, 2, 3, 5, 6, 7, 4, 15,12,13,14, 8);
AXR(10,11, 8, 9, 15,12,13,14, 5, 6, 7, 4, 7);
- bnez $at, .Loop_chacha20_xor_rounds
+ bnez $at, .Loop_chacha_xor_rounds
addiu BYTES, -(CHACHA20_BLOCK_SIZE)
/* Is data src/dst unaligned? Jump */
- bnez IS_UNALIGNED, .Loop_chacha20_unaligned
+ bnez IS_UNALIGNED, .Loop_chacha_unaligned
/* Set number rounds here to fill delayslot. */
- li $at, 20
+ lw $at, (STACK_SIZE+16)($sp)
/* BYTES < 0, it has no full block. */
- bltz BYTES, .Lchacha20_mips_no_full_block_aligned
+ bltz BYTES, .Lchacha_mips_no_full_block_aligned
FOR_EACH_WORD_REV(STORE_ALIGNED)
/* BYTES > 0? Loop again. */
- bgtz BYTES, .Loop_chacha20_rounds
+ bgtz BYTES, .Loop_chacha_rounds
/* Place this here to fill delay slot */
addiu NONCE_0, 1
/* BYTES < 0? Handle last bytes */
- bltz BYTES, .Lchacha20_mips_xor_bytes
+ bltz BYTES, .Lchacha_mips_xor_bytes
-.Lchacha20_mips_xor_done:
+.Lchacha_mips_xor_done:
/* Restore used registers */
lw $s0, 0($sp)
lw $s1, 4($sp)
@@ -307,11 +307,11 @@ chacha20_mips:
/* Write NONCE_0 back to right location in state */
sw NONCE_0, 48(STATE)
-.Lchacha20_mips_end:
+.Lchacha_mips_end:
addiu $sp, STACK_SIZE
jr $ra
-.Lchacha20_mips_no_full_block_aligned:
+.Lchacha_mips_no_full_block_aligned:
/* Restore the offset on BYTES */
addiu BYTES, CHACHA20_BLOCK_SIZE
@@ -319,7 +319,7 @@ chacha20_mips:
andi $at, BYTES, MASK_U32
/* Load upper half of jump table addr */
- lui T0, %hi(.Lchacha20_mips_jmptbl_aligned_0)
+ lui T0, %hi(.Lchacha_mips_jmptbl_aligned_0)
/* Calculate lower half jump table offset */
ins T0, $at, 1, 6
@@ -328,7 +328,7 @@ chacha20_mips:
addu T1, STATE, $at
/* Add lower half jump table addr */
- addiu T0, %lo(.Lchacha20_mips_jmptbl_aligned_0)
+ addiu T0, %lo(.Lchacha_mips_jmptbl_aligned_0)
/* Read value from STATE */
lw SAVED_CA, 0(T1)
@@ -342,31 +342,31 @@ chacha20_mips:
FOR_EACH_WORD(JMPTBL_ALIGNED)
-.Loop_chacha20_unaligned:
+.Loop_chacha_unaligned:
/* Set number rounds here to fill delayslot. */
- li $at, 20
+ lw $at, (STACK_SIZE+16)($sp)
/* BYTES > 0, it has no full block. */
- bltz BYTES, .Lchacha20_mips_no_full_block_unaligned
+ bltz BYTES, .Lchacha_mips_no_full_block_unaligned
FOR_EACH_WORD_REV(STORE_UNALIGNED)
/* BYTES > 0? Loop again. */
- bgtz BYTES, .Loop_chacha20_rounds
+ bgtz BYTES, .Loop_chacha_rounds
/* Write NONCE_0 back to right location in state */
sw NONCE_0, 48(STATE)
.set noreorder
/* Fall through to byte handling */
- bgez BYTES, .Lchacha20_mips_xor_done
-.Lchacha20_mips_xor_unaligned_0_b:
-.Lchacha20_mips_xor_aligned_0_b:
+ bgez BYTES, .Lchacha_mips_xor_done
+.Lchacha_mips_xor_unaligned_0_b:
+.Lchacha_mips_xor_aligned_0_b:
/* Place this here to fill delay slot */
addiu NONCE_0, 1
.set reorder
-.Lchacha20_mips_xor_bytes:
+.Lchacha_mips_xor_bytes:
addu IN, $at
addu OUT, $at
/* First byte */
@@ -376,22 +376,22 @@ chacha20_mips:
ROTR(SAVED_X)
xor T1, SAVED_X
sb T1, 0(OUT)
- beqz $at, .Lchacha20_mips_xor_done
+ beqz $at, .Lchacha_mips_xor_done
/* Second byte */
lbu T1, 1(IN)
addiu $at, BYTES, 2
ROTx SAVED_X, 8
xor T1, SAVED_X
sb T1, 1(OUT)
- beqz $at, .Lchacha20_mips_xor_done
+ beqz $at, .Lchacha_mips_xor_done
/* Third byte */
lbu T1, 2(IN)
ROTx SAVED_X, 8
xor T1, SAVED_X
sb T1, 2(OUT)
- b .Lchacha20_mips_xor_done
+ b .Lchacha_mips_xor_done
-.Lchacha20_mips_no_full_block_unaligned:
+.Lchacha_mips_no_full_block_unaligned:
/* Restore the offset on BYTES */
addiu BYTES, CHACHA20_BLOCK_SIZE
@@ -399,7 +399,7 @@ chacha20_mips:
andi $at, BYTES, MASK_U32
/* Load upper half of jump table addr */
- lui T0, %hi(.Lchacha20_mips_jmptbl_unaligned_0)
+ lui T0, %hi(.Lchacha_mips_jmptbl_unaligned_0)
/* Calculate lower half jump table offset */
ins T0, $at, 1, 6
@@ -408,7 +408,7 @@ chacha20_mips:
addu T1, STATE, $at
/* Add lower half jump table addr */
- addiu T0, %lo(.Lchacha20_mips_jmptbl_unaligned_0)
+ addiu T0, %lo(.Lchacha_mips_jmptbl_unaligned_0)
/* Read value from STATE */
lw SAVED_CA, 0(T1)
@@ -420,5 +420,78 @@ chacha20_mips:
/* Jump table */
FOR_EACH_WORD(JMPTBL_UNALIGNED)
-.end chacha20_mips
+.end chacha_crypt_arch
+.set at
+
+/* Input arguments
+ * STATE $a0
+ * OUT $a1
+ * NROUND $a2
+ */
+
+#undef X12
+#undef X13
+#undef X14
+#undef X15
+
+#define X12 $a3
+#define X13 $at
+#define X14 $v0
+#define X15 STATE
+
+.set noat
+.globl hchacha_block_arch
+.ent hchacha_block_arch
+hchacha_block_arch:
+ .frame $sp, STACK_SIZE, $ra
+
+ addiu $sp, -STACK_SIZE
+
+ /* Save X11(s6) */
+ sw X11, 0($sp)
+
+ lw X0, 0(STATE)
+ lw X1, 4(STATE)
+ lw X2, 8(STATE)
+ lw X3, 12(STATE)
+ lw X4, 16(STATE)
+ lw X5, 20(STATE)
+ lw X6, 24(STATE)
+ lw X7, 28(STATE)
+ lw X8, 32(STATE)
+ lw X9, 36(STATE)
+ lw X10, 40(STATE)
+ lw X11, 44(STATE)
+ lw X12, 48(STATE)
+ lw X13, 52(STATE)
+ lw X14, 56(STATE)
+ lw X15, 60(STATE)
+
+.Loop_hchacha_xor_rounds:
+ addiu $a2, -2
+ AXR( 0, 1, 2, 3, 4, 5, 6, 7, 12,13,14,15, 16);
+ AXR( 8, 9,10,11, 12,13,14,15, 4, 5, 6, 7, 12);
+ AXR( 0, 1, 2, 3, 4, 5, 6, 7, 12,13,14,15, 8);
+ AXR( 8, 9,10,11, 12,13,14,15, 4, 5, 6, 7, 7);
+ AXR( 0, 1, 2, 3, 5, 6, 7, 4, 15,12,13,14, 16);
+ AXR(10,11, 8, 9, 15,12,13,14, 5, 6, 7, 4, 12);
+ AXR( 0, 1, 2, 3, 5, 6, 7, 4, 15,12,13,14, 8);
+ AXR(10,11, 8, 9, 15,12,13,14, 5, 6, 7, 4, 7);
+ bnez $a2, .Loop_hchacha_xor_rounds
+
+ /* Restore used register */
+ lw X11, 0($sp)
+
+ sw X0, 0(OUT)
+ sw X1, 4(OUT)
+ sw X2, 8(OUT)
+ sw X3, 12(OUT)
+ sw X12, 16(OUT)
+ sw X13, 20(OUT)
+ sw X14, 24(OUT)
+ sw X15, 28(OUT)
+
+ addiu $sp, STACK_SIZE
+ jr $ra
+.end hchacha_block_arch
.set at
--- /dev/null
+++ b/arch/mips/crypto/chacha-glue.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MIPS accelerated ChaCha and XChaCha stream ciphers,
+ * including ChaCha20 (RFC7539)
+ *
+ * Copyright (C) 2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
+ */
+
+#include <asm/byteorder.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/chacha.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+asmlinkage void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes, int nrounds);
+EXPORT_SYMBOL(chacha_crypt_arch);
+
+asmlinkage void hchacha_block_arch(const u32 *state, u32 *stream, int nrounds);
+EXPORT_SYMBOL(hchacha_block_arch);
+
+void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv)
+{
+ chacha_init_generic(state, key, iv);
+}
+EXPORT_SYMBOL(chacha_init_arch);
+
+static int chacha_mips_stream_xor(struct skcipher_request *req,
+ const struct chacha_ctx *ctx, const u8 *iv)
+{
+ struct skcipher_walk walk;
+ u32 state[16];
+ int err;
+
+ err = skcipher_walk_virt(&walk, req, false);
+
+ chacha_init_generic(state, ctx->key, iv);
+
+ while (walk.nbytes > 0) {
+ unsigned int nbytes = walk.nbytes;
+
+ if (nbytes < walk.total)
+ nbytes = round_down(nbytes, walk.stride);
+
+ chacha_crypt(state, walk.dst.virt.addr, walk.src.virt.addr,
+ nbytes, ctx->nrounds);
+ err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
+ }
+
+ return err;
+}
+
+static int chacha_mips(struct skcipher_request *req)
+{
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+ return chacha_mips_stream_xor(req, ctx, req->iv);
+}
+
+static int xchacha_mips(struct skcipher_request *req)
+{
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
+ struct chacha_ctx subctx;
+ u32 state[16];
+ u8 real_iv[16];
+
+ chacha_init_generic(state, ctx->key, req->iv);
+
+ hchacha_block(state, subctx.key, ctx->nrounds);
+ subctx.nrounds = ctx->nrounds;
+
+ memcpy(&real_iv[0], req->iv + 24, 8);
+ memcpy(&real_iv[8], req->iv + 16, 8);
+ return chacha_mips_stream_xor(req, &subctx, real_iv);
+}
+
+static struct skcipher_alg algs[] = {
+ {
+ .base.cra_name = "chacha20",
+ .base.cra_driver_name = "chacha20-mips",
+ .base.cra_priority = 200,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = CHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .setkey = chacha20_setkey,
+ .encrypt = chacha_mips,
+ .decrypt = chacha_mips,
+ }, {
+ .base.cra_name = "xchacha20",
+ .base.cra_driver_name = "xchacha20-mips",
+ .base.cra_priority = 200,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = XCHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .setkey = chacha20_setkey,
+ .encrypt = xchacha_mips,
+ .decrypt = xchacha_mips,
+ }, {
+ .base.cra_name = "xchacha12",
+ .base.cra_driver_name = "xchacha12-mips",
+ .base.cra_priority = 200,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha_ctx),
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA_KEY_SIZE,
+ .max_keysize = CHACHA_KEY_SIZE,
+ .ivsize = XCHACHA_IV_SIZE,
+ .chunksize = CHACHA_BLOCK_SIZE,
+ .setkey = chacha12_setkey,
+ .encrypt = xchacha_mips,
+ .decrypt = xchacha_mips,
+ }
+};
+
+static int __init chacha_simd_mod_init(void)
+{
+ return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
+}
+
+static void __exit chacha_simd_mod_fini(void)
+{
+ crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
+}
+
+module_init(chacha_simd_mod_init);
+module_exit(chacha_simd_mod_fini);
+
+MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (MIPS accelerated)");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("chacha20");
+MODULE_ALIAS_CRYPTO("chacha20-mips");
+MODULE_ALIAS_CRYPTO("xchacha20");
+MODULE_ALIAS_CRYPTO("xchacha20-mips");
+MODULE_ALIAS_CRYPTO("xchacha12");
+MODULE_ALIAS_CRYPTO("xchacha12-mips");
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1423,6 +1423,12 @@ config CRYPTO_CHACHA20_X86_64
SSSE3, AVX2, and AVX-512VL optimized implementations of the ChaCha20,
XChaCha20, and XChaCha12 stream ciphers.
+config CRYPTO_CHACHA_MIPS
+ tristate "ChaCha stream cipher algorithms (MIPS 32r2 optimized)"
+ depends on CPU_MIPS32_R2
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_ARCH_HAVE_LIB_CHACHA
+
config CRYPTO_SEED
tristate "SEED cipher algorithm"
select CRYPTO_ALGAPI

View File

@@ -1,115 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:18 +0100
Subject: [PATCH] crypto: chacha - unexport chacha_generic routines
commit 22cf705360707ced15f9fe5423938f313c7df536 upstream.
Now that all users of generic ChaCha code have moved to the core library,
there is no longer a need for the generic ChaCha skcpiher driver to
export parts of it implementation for reuse by other drivers. So drop
the exports, and make the symbols static.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
crypto/chacha_generic.c | 26 ++++++++------------------
include/crypto/internal/chacha.h | 10 ----------
2 files changed, 8 insertions(+), 28 deletions(-)
--- a/crypto/chacha_generic.c
+++ b/crypto/chacha_generic.c
@@ -21,7 +21,7 @@ static int chacha_stream_xor(struct skci
err = skcipher_walk_virt(&walk, req, false);
- crypto_chacha_init(state, ctx, iv);
+ chacha_init_generic(state, ctx->key, iv);
while (walk.nbytes > 0) {
unsigned int nbytes = walk.nbytes;
@@ -37,36 +37,27 @@ static int chacha_stream_xor(struct skci
return err;
}
-void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv)
-{
- chacha_init_generic(state, ctx->key, iv);
-}
-EXPORT_SYMBOL_GPL(crypto_chacha_init);
-
-int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
- unsigned int keysize)
+static int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ unsigned int keysize)
{
return chacha_setkey(tfm, key, keysize, 20);
}
-EXPORT_SYMBOL_GPL(crypto_chacha20_setkey);
-int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
- unsigned int keysize)
+static int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ unsigned int keysize)
{
return chacha_setkey(tfm, key, keysize, 12);
}
-EXPORT_SYMBOL_GPL(crypto_chacha12_setkey);
-int crypto_chacha_crypt(struct skcipher_request *req)
+static int crypto_chacha_crypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
return chacha_stream_xor(req, ctx, req->iv);
}
-EXPORT_SYMBOL_GPL(crypto_chacha_crypt);
-int crypto_xchacha_crypt(struct skcipher_request *req)
+static int crypto_xchacha_crypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
@@ -75,7 +66,7 @@ int crypto_xchacha_crypt(struct skcipher
u8 real_iv[16];
/* Compute the subkey given the original key and first 128 nonce bits */
- crypto_chacha_init(state, ctx, req->iv);
+ chacha_init_generic(state, ctx->key, req->iv);
hchacha_block_generic(state, subctx.key, ctx->nrounds);
subctx.nrounds = ctx->nrounds;
@@ -86,7 +77,6 @@ int crypto_xchacha_crypt(struct skcipher
/* Generate the stream and XOR it with the data */
return chacha_stream_xor(req, &subctx, real_iv);
}
-EXPORT_SYMBOL_GPL(crypto_xchacha_crypt);
static struct skcipher_alg algs[] = {
{
--- a/include/crypto/internal/chacha.h
+++ b/include/crypto/internal/chacha.h
@@ -12,8 +12,6 @@ struct chacha_ctx {
int nrounds;
};
-void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv);
-
static inline int chacha_setkey(struct crypto_skcipher *tfm, const u8 *key,
unsigned int keysize, int nrounds)
{
@@ -42,12 +40,4 @@ static int inline chacha12_setkey(struct
return chacha_setkey(tfm, key, keysize, 12);
}
-int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
- unsigned int keysize);
-int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
- unsigned int keysize);
-
-int crypto_chacha_crypt(struct skcipher_request *req);
-int crypto_xchacha_crypt(struct skcipher_request *req);
-
#endif /* _CRYPTO_CHACHA_H */

View File

@@ -1,649 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:19 +0100
Subject: [PATCH] crypto: poly1305 - move core routines into a separate library
commit 48ea8c6ebc96bc0990e12ee1c43d0832c23576bb upstream.
Move the core Poly1305 routines shared between the generic Poly1305
shash driver and the Adiantum and NHPoly1305 drivers into a separate
library so that using just this pieces does not pull in the crypto
API pieces of the generic Poly1305 routine.
In a subsequent patch, we will augment this generic library with
init/update/final routines so that Poyl1305 algorithm can be used
directly without the need for using the crypto API's shash abstraction.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/x86/crypto/poly1305_glue.c | 2 +-
crypto/Kconfig | 5 +-
crypto/adiantum.c | 5 +-
crypto/nhpoly1305.c | 3 +-
crypto/poly1305_generic.c | 195 ++---------------------------
include/crypto/internal/poly1305.h | 67 ++++++++++
include/crypto/poly1305.h | 23 ----
lib/crypto/Kconfig | 3 +
lib/crypto/Makefile | 3 +
lib/crypto/poly1305.c | 158 +++++++++++++++++++++++
10 files changed, 248 insertions(+), 216 deletions(-)
create mode 100644 include/crypto/internal/poly1305.h
create mode 100644 lib/crypto/poly1305.c
--- a/arch/x86/crypto/poly1305_glue.c
+++ b/arch/x86/crypto/poly1305_glue.c
@@ -7,8 +7,8 @@
#include <crypto/algapi.h>
#include <crypto/internal/hash.h>
+#include <crypto/internal/poly1305.h>
#include <crypto/internal/simd.h>
-#include <crypto/poly1305.h>
#include <linux/crypto.h>
#include <linux/kernel.h>
#include <linux/module.h>
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -446,7 +446,7 @@ config CRYPTO_KEYWRAP
config CRYPTO_NHPOLY1305
tristate
select CRYPTO_HASH
- select CRYPTO_POLY1305
+ select CRYPTO_LIB_POLY1305_GENERIC
config CRYPTO_NHPOLY1305_SSE2
tristate "NHPoly1305 hash function (x86_64 SSE2 implementation)"
@@ -467,7 +467,7 @@ config CRYPTO_NHPOLY1305_AVX2
config CRYPTO_ADIANTUM
tristate "Adiantum support"
select CRYPTO_CHACHA20
- select CRYPTO_POLY1305
+ select CRYPTO_LIB_POLY1305_GENERIC
select CRYPTO_NHPOLY1305
select CRYPTO_MANAGER
help
@@ -686,6 +686,7 @@ config CRYPTO_GHASH
config CRYPTO_POLY1305
tristate "Poly1305 authenticator algorithm"
select CRYPTO_HASH
+ select CRYPTO_LIB_POLY1305_GENERIC
help
Poly1305 authenticator algorithm, RFC7539.
--- a/crypto/adiantum.c
+++ b/crypto/adiantum.c
@@ -33,6 +33,7 @@
#include <crypto/b128ops.h>
#include <crypto/chacha.h>
#include <crypto/internal/hash.h>
+#include <crypto/internal/poly1305.h>
#include <crypto/internal/skcipher.h>
#include <crypto/nhpoly1305.h>
#include <crypto/scatterwalk.h>
@@ -242,11 +243,11 @@ static void adiantum_hash_header(struct
BUILD_BUG_ON(sizeof(header) % POLY1305_BLOCK_SIZE != 0);
poly1305_core_blocks(&state, &tctx->header_hash_key,
- &header, sizeof(header) / POLY1305_BLOCK_SIZE);
+ &header, sizeof(header) / POLY1305_BLOCK_SIZE, 1);
BUILD_BUG_ON(TWEAK_SIZE % POLY1305_BLOCK_SIZE != 0);
poly1305_core_blocks(&state, &tctx->header_hash_key, req->iv,
- TWEAK_SIZE / POLY1305_BLOCK_SIZE);
+ TWEAK_SIZE / POLY1305_BLOCK_SIZE, 1);
poly1305_core_emit(&state, &rctx->header_hash);
}
--- a/crypto/nhpoly1305.c
+++ b/crypto/nhpoly1305.c
@@ -33,6 +33,7 @@
#include <asm/unaligned.h>
#include <crypto/algapi.h>
#include <crypto/internal/hash.h>
+#include <crypto/internal/poly1305.h>
#include <crypto/nhpoly1305.h>
#include <linux/crypto.h>
#include <linux/kernel.h>
@@ -78,7 +79,7 @@ static void process_nh_hash_value(struct
BUILD_BUG_ON(NH_HASH_BYTES % POLY1305_BLOCK_SIZE != 0);
poly1305_core_blocks(&state->poly_state, &key->poly_key, state->nh_hash,
- NH_HASH_BYTES / POLY1305_BLOCK_SIZE);
+ NH_HASH_BYTES / POLY1305_BLOCK_SIZE, 1);
}
/*
--- a/crypto/poly1305_generic.c
+++ b/crypto/poly1305_generic.c
@@ -13,27 +13,12 @@
#include <crypto/algapi.h>
#include <crypto/internal/hash.h>
-#include <crypto/poly1305.h>
+#include <crypto/internal/poly1305.h>
#include <linux/crypto.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/unaligned.h>
-static inline u64 mlt(u64 a, u64 b)
-{
- return a * b;
-}
-
-static inline u32 sr(u64 v, u_char n)
-{
- return v >> n;
-}
-
-static inline u32 and(u32 v, u32 mask)
-{
- return v & mask;
-}
-
int crypto_poly1305_init(struct shash_desc *desc)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
@@ -47,124 +32,8 @@ int crypto_poly1305_init(struct shash_de
}
EXPORT_SYMBOL_GPL(crypto_poly1305_init);
-void poly1305_core_setkey(struct poly1305_key *key, const u8 *raw_key)
-{
- /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
- key->r[0] = (get_unaligned_le32(raw_key + 0) >> 0) & 0x3ffffff;
- key->r[1] = (get_unaligned_le32(raw_key + 3) >> 2) & 0x3ffff03;
- key->r[2] = (get_unaligned_le32(raw_key + 6) >> 4) & 0x3ffc0ff;
- key->r[3] = (get_unaligned_le32(raw_key + 9) >> 6) & 0x3f03fff;
- key->r[4] = (get_unaligned_le32(raw_key + 12) >> 8) & 0x00fffff;
-}
-EXPORT_SYMBOL_GPL(poly1305_core_setkey);
-
-/*
- * Poly1305 requires a unique key for each tag, which implies that we can't set
- * it on the tfm that gets accessed by multiple users simultaneously. Instead we
- * expect the key as the first 32 bytes in the update() call.
- */
-unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
- const u8 *src, unsigned int srclen)
-{
- if (!dctx->sset) {
- if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) {
- poly1305_core_setkey(&dctx->r, src);
- src += POLY1305_BLOCK_SIZE;
- srclen -= POLY1305_BLOCK_SIZE;
- dctx->rset = true;
- }
- if (srclen >= POLY1305_BLOCK_SIZE) {
- dctx->s[0] = get_unaligned_le32(src + 0);
- dctx->s[1] = get_unaligned_le32(src + 4);
- dctx->s[2] = get_unaligned_le32(src + 8);
- dctx->s[3] = get_unaligned_le32(src + 12);
- src += POLY1305_BLOCK_SIZE;
- srclen -= POLY1305_BLOCK_SIZE;
- dctx->sset = true;
- }
- }
- return srclen;
-}
-EXPORT_SYMBOL_GPL(crypto_poly1305_setdesckey);
-
-static void poly1305_blocks_internal(struct poly1305_state *state,
- const struct poly1305_key *key,
- const void *src, unsigned int nblocks,
- u32 hibit)
-{
- u32 r0, r1, r2, r3, r4;
- u32 s1, s2, s3, s4;
- u32 h0, h1, h2, h3, h4;
- u64 d0, d1, d2, d3, d4;
-
- if (!nblocks)
- return;
-
- r0 = key->r[0];
- r1 = key->r[1];
- r2 = key->r[2];
- r3 = key->r[3];
- r4 = key->r[4];
-
- s1 = r1 * 5;
- s2 = r2 * 5;
- s3 = r3 * 5;
- s4 = r4 * 5;
-
- h0 = state->h[0];
- h1 = state->h[1];
- h2 = state->h[2];
- h3 = state->h[3];
- h4 = state->h[4];
-
- do {
- /* h += m[i] */
- h0 += (get_unaligned_le32(src + 0) >> 0) & 0x3ffffff;
- h1 += (get_unaligned_le32(src + 3) >> 2) & 0x3ffffff;
- h2 += (get_unaligned_le32(src + 6) >> 4) & 0x3ffffff;
- h3 += (get_unaligned_le32(src + 9) >> 6) & 0x3ffffff;
- h4 += (get_unaligned_le32(src + 12) >> 8) | hibit;
-
- /* h *= r */
- d0 = mlt(h0, r0) + mlt(h1, s4) + mlt(h2, s3) +
- mlt(h3, s2) + mlt(h4, s1);
- d1 = mlt(h0, r1) + mlt(h1, r0) + mlt(h2, s4) +
- mlt(h3, s3) + mlt(h4, s2);
- d2 = mlt(h0, r2) + mlt(h1, r1) + mlt(h2, r0) +
- mlt(h3, s4) + mlt(h4, s3);
- d3 = mlt(h0, r3) + mlt(h1, r2) + mlt(h2, r1) +
- mlt(h3, r0) + mlt(h4, s4);
- d4 = mlt(h0, r4) + mlt(h1, r3) + mlt(h2, r2) +
- mlt(h3, r1) + mlt(h4, r0);
-
- /* (partial) h %= p */
- d1 += sr(d0, 26); h0 = and(d0, 0x3ffffff);
- d2 += sr(d1, 26); h1 = and(d1, 0x3ffffff);
- d3 += sr(d2, 26); h2 = and(d2, 0x3ffffff);
- d4 += sr(d3, 26); h3 = and(d3, 0x3ffffff);
- h0 += sr(d4, 26) * 5; h4 = and(d4, 0x3ffffff);
- h1 += h0 >> 26; h0 = h0 & 0x3ffffff;
-
- src += POLY1305_BLOCK_SIZE;
- } while (--nblocks);
-
- state->h[0] = h0;
- state->h[1] = h1;
- state->h[2] = h2;
- state->h[3] = h3;
- state->h[4] = h4;
-}
-
-void poly1305_core_blocks(struct poly1305_state *state,
- const struct poly1305_key *key,
- const void *src, unsigned int nblocks)
-{
- poly1305_blocks_internal(state, key, src, nblocks, 1 << 24);
-}
-EXPORT_SYMBOL_GPL(poly1305_core_blocks);
-
-static void poly1305_blocks(struct poly1305_desc_ctx *dctx,
- const u8 *src, unsigned int srclen, u32 hibit)
+static void poly1305_blocks(struct poly1305_desc_ctx *dctx, const u8 *src,
+ unsigned int srclen)
{
unsigned int datalen;
@@ -174,8 +43,8 @@ static void poly1305_blocks(struct poly1
srclen = datalen;
}
- poly1305_blocks_internal(&dctx->h, &dctx->r,
- src, srclen / POLY1305_BLOCK_SIZE, hibit);
+ poly1305_core_blocks(&dctx->h, &dctx->r, src,
+ srclen / POLY1305_BLOCK_SIZE, 1);
}
int crypto_poly1305_update(struct shash_desc *desc,
@@ -193,13 +62,13 @@ int crypto_poly1305_update(struct shash_
if (dctx->buflen == POLY1305_BLOCK_SIZE) {
poly1305_blocks(dctx, dctx->buf,
- POLY1305_BLOCK_SIZE, 1 << 24);
+ POLY1305_BLOCK_SIZE);
dctx->buflen = 0;
}
}
if (likely(srclen >= POLY1305_BLOCK_SIZE)) {
- poly1305_blocks(dctx, src, srclen, 1 << 24);
+ poly1305_blocks(dctx, src, srclen);
src += srclen - (srclen % POLY1305_BLOCK_SIZE);
srclen %= POLY1305_BLOCK_SIZE;
}
@@ -213,54 +82,6 @@ int crypto_poly1305_update(struct shash_
}
EXPORT_SYMBOL_GPL(crypto_poly1305_update);
-void poly1305_core_emit(const struct poly1305_state *state, void *dst)
-{
- u32 h0, h1, h2, h3, h4;
- u32 g0, g1, g2, g3, g4;
- u32 mask;
-
- /* fully carry h */
- h0 = state->h[0];
- h1 = state->h[1];
- h2 = state->h[2];
- h3 = state->h[3];
- h4 = state->h[4];
-
- h2 += (h1 >> 26); h1 = h1 & 0x3ffffff;
- h3 += (h2 >> 26); h2 = h2 & 0x3ffffff;
- h4 += (h3 >> 26); h3 = h3 & 0x3ffffff;
- h0 += (h4 >> 26) * 5; h4 = h4 & 0x3ffffff;
- h1 += (h0 >> 26); h0 = h0 & 0x3ffffff;
-
- /* compute h + -p */
- g0 = h0 + 5;
- g1 = h1 + (g0 >> 26); g0 &= 0x3ffffff;
- g2 = h2 + (g1 >> 26); g1 &= 0x3ffffff;
- g3 = h3 + (g2 >> 26); g2 &= 0x3ffffff;
- g4 = h4 + (g3 >> 26) - (1 << 26); g3 &= 0x3ffffff;
-
- /* select h if h < p, or h + -p if h >= p */
- mask = (g4 >> ((sizeof(u32) * 8) - 1)) - 1;
- g0 &= mask;
- g1 &= mask;
- g2 &= mask;
- g3 &= mask;
- g4 &= mask;
- mask = ~mask;
- h0 = (h0 & mask) | g0;
- h1 = (h1 & mask) | g1;
- h2 = (h2 & mask) | g2;
- h3 = (h3 & mask) | g3;
- h4 = (h4 & mask) | g4;
-
- /* h = h % (2^128) */
- put_unaligned_le32((h0 >> 0) | (h1 << 26), dst + 0);
- put_unaligned_le32((h1 >> 6) | (h2 << 20), dst + 4);
- put_unaligned_le32((h2 >> 12) | (h3 << 14), dst + 8);
- put_unaligned_le32((h3 >> 18) | (h4 << 8), dst + 12);
-}
-EXPORT_SYMBOL_GPL(poly1305_core_emit);
-
int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
@@ -274,7 +95,7 @@ int crypto_poly1305_final(struct shash_d
dctx->buf[dctx->buflen++] = 1;
memset(dctx->buf + dctx->buflen, 0,
POLY1305_BLOCK_SIZE - dctx->buflen);
- poly1305_blocks(dctx, dctx->buf, POLY1305_BLOCK_SIZE, 0);
+ poly1305_core_blocks(&dctx->h, &dctx->r, dctx->buf, 1, 0);
}
poly1305_core_emit(&dctx->h, digest);
--- /dev/null
+++ b/include/crypto/internal/poly1305.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Common values for the Poly1305 algorithm
+ */
+
+#ifndef _CRYPTO_INTERNAL_POLY1305_H
+#define _CRYPTO_INTERNAL_POLY1305_H
+
+#include <asm/unaligned.h>
+#include <linux/types.h>
+#include <crypto/poly1305.h>
+
+struct shash_desc;
+
+/*
+ * Poly1305 core functions. These implement the ε-almost-∆-universal hash
+ * function underlying the Poly1305 MAC, i.e. they don't add an encrypted nonce
+ * ("s key") at the end. They also only support block-aligned inputs.
+ */
+void poly1305_core_setkey(struct poly1305_key *key, const u8 *raw_key);
+static inline void poly1305_core_init(struct poly1305_state *state)
+{
+ *state = (struct poly1305_state){};
+}
+
+void poly1305_core_blocks(struct poly1305_state *state,
+ const struct poly1305_key *key, const void *src,
+ unsigned int nblocks, u32 hibit);
+void poly1305_core_emit(const struct poly1305_state *state, void *dst);
+
+/* Crypto API helper functions for the Poly1305 MAC */
+int crypto_poly1305_init(struct shash_desc *desc);
+
+int crypto_poly1305_update(struct shash_desc *desc,
+ const u8 *src, unsigned int srclen);
+int crypto_poly1305_final(struct shash_desc *desc, u8 *dst);
+
+/*
+ * Poly1305 requires a unique key for each tag, which implies that we can't set
+ * it on the tfm that gets accessed by multiple users simultaneously. Instead we
+ * expect the key as the first 32 bytes in the update() call.
+ */
+static inline
+unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
+ const u8 *src, unsigned int srclen)
+{
+ if (!dctx->sset) {
+ if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) {
+ poly1305_core_setkey(&dctx->r, src);
+ src += POLY1305_BLOCK_SIZE;
+ srclen -= POLY1305_BLOCK_SIZE;
+ dctx->rset = true;
+ }
+ if (srclen >= POLY1305_BLOCK_SIZE) {
+ dctx->s[0] = get_unaligned_le32(src + 0);
+ dctx->s[1] = get_unaligned_le32(src + 4);
+ dctx->s[2] = get_unaligned_le32(src + 8);
+ dctx->s[3] = get_unaligned_le32(src + 12);
+ src += POLY1305_BLOCK_SIZE;
+ srclen -= POLY1305_BLOCK_SIZE;
+ dctx->sset = true;
+ }
+ }
+ return srclen;
+}
+
+#endif
--- a/include/crypto/poly1305.h
+++ b/include/crypto/poly1305.h
@@ -38,27 +38,4 @@ struct poly1305_desc_ctx {
bool sset;
};
-/*
- * Poly1305 core functions. These implement the ε-almost-∆-universal hash
- * function underlying the Poly1305 MAC, i.e. they don't add an encrypted nonce
- * ("s key") at the end. They also only support block-aligned inputs.
- */
-void poly1305_core_setkey(struct poly1305_key *key, const u8 *raw_key);
-static inline void poly1305_core_init(struct poly1305_state *state)
-{
- memset(state->h, 0, sizeof(state->h));
-}
-void poly1305_core_blocks(struct poly1305_state *state,
- const struct poly1305_key *key,
- const void *src, unsigned int nblocks);
-void poly1305_core_emit(const struct poly1305_state *state, void *dst);
-
-/* Crypto API helper functions for the Poly1305 MAC */
-int crypto_poly1305_init(struct shash_desc *desc);
-unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
- const u8 *src, unsigned int srclen);
-int crypto_poly1305_update(struct shash_desc *desc,
- const u8 *src, unsigned int srclen);
-int crypto_poly1305_final(struct shash_desc *desc, u8 *dst);
-
#endif
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -37,5 +37,8 @@ config CRYPTO_LIB_CHACHA
config CRYPTO_LIB_DES
tristate
+config CRYPTO_LIB_POLY1305_GENERIC
+ tristate
+
config CRYPTO_LIB_SHA256
tristate
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -13,5 +13,8 @@ libarc4-y := arc4.o
obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o
libdes-y := des.o
+obj-$(CONFIG_CRYPTO_LIB_POLY1305_GENERIC) += libpoly1305.o
+libpoly1305-y := poly1305.o
+
obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o
libsha256-y := sha256.o
--- /dev/null
+++ b/lib/crypto/poly1305.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Poly1305 authenticator algorithm, RFC7539
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * Based on public domain code by Andrew Moon and Daniel J. Bernstein.
+ */
+
+#include <crypto/internal/poly1305.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+
+static inline u64 mlt(u64 a, u64 b)
+{
+ return a * b;
+}
+
+static inline u32 sr(u64 v, u_char n)
+{
+ return v >> n;
+}
+
+static inline u32 and(u32 v, u32 mask)
+{
+ return v & mask;
+}
+
+void poly1305_core_setkey(struct poly1305_key *key, const u8 *raw_key)
+{
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+ key->r[0] = (get_unaligned_le32(raw_key + 0) >> 0) & 0x3ffffff;
+ key->r[1] = (get_unaligned_le32(raw_key + 3) >> 2) & 0x3ffff03;
+ key->r[2] = (get_unaligned_le32(raw_key + 6) >> 4) & 0x3ffc0ff;
+ key->r[3] = (get_unaligned_le32(raw_key + 9) >> 6) & 0x3f03fff;
+ key->r[4] = (get_unaligned_le32(raw_key + 12) >> 8) & 0x00fffff;
+}
+EXPORT_SYMBOL_GPL(poly1305_core_setkey);
+
+void poly1305_core_blocks(struct poly1305_state *state,
+ const struct poly1305_key *key, const void *src,
+ unsigned int nblocks, u32 hibit)
+{
+ u32 r0, r1, r2, r3, r4;
+ u32 s1, s2, s3, s4;
+ u32 h0, h1, h2, h3, h4;
+ u64 d0, d1, d2, d3, d4;
+
+ if (!nblocks)
+ return;
+
+ r0 = key->r[0];
+ r1 = key->r[1];
+ r2 = key->r[2];
+ r3 = key->r[3];
+ r4 = key->r[4];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ h0 = state->h[0];
+ h1 = state->h[1];
+ h2 = state->h[2];
+ h3 = state->h[3];
+ h4 = state->h[4];
+
+ do {
+ /* h += m[i] */
+ h0 += (get_unaligned_le32(src + 0) >> 0) & 0x3ffffff;
+ h1 += (get_unaligned_le32(src + 3) >> 2) & 0x3ffffff;
+ h2 += (get_unaligned_le32(src + 6) >> 4) & 0x3ffffff;
+ h3 += (get_unaligned_le32(src + 9) >> 6) & 0x3ffffff;
+ h4 += (get_unaligned_le32(src + 12) >> 8) | (hibit << 24);
+
+ /* h *= r */
+ d0 = mlt(h0, r0) + mlt(h1, s4) + mlt(h2, s3) +
+ mlt(h3, s2) + mlt(h4, s1);
+ d1 = mlt(h0, r1) + mlt(h1, r0) + mlt(h2, s4) +
+ mlt(h3, s3) + mlt(h4, s2);
+ d2 = mlt(h0, r2) + mlt(h1, r1) + mlt(h2, r0) +
+ mlt(h3, s4) + mlt(h4, s3);
+ d3 = mlt(h0, r3) + mlt(h1, r2) + mlt(h2, r1) +
+ mlt(h3, r0) + mlt(h4, s4);
+ d4 = mlt(h0, r4) + mlt(h1, r3) + mlt(h2, r2) +
+ mlt(h3, r1) + mlt(h4, r0);
+
+ /* (partial) h %= p */
+ d1 += sr(d0, 26); h0 = and(d0, 0x3ffffff);
+ d2 += sr(d1, 26); h1 = and(d1, 0x3ffffff);
+ d3 += sr(d2, 26); h2 = and(d2, 0x3ffffff);
+ d4 += sr(d3, 26); h3 = and(d3, 0x3ffffff);
+ h0 += sr(d4, 26) * 5; h4 = and(d4, 0x3ffffff);
+ h1 += h0 >> 26; h0 = h0 & 0x3ffffff;
+
+ src += POLY1305_BLOCK_SIZE;
+ } while (--nblocks);
+
+ state->h[0] = h0;
+ state->h[1] = h1;
+ state->h[2] = h2;
+ state->h[3] = h3;
+ state->h[4] = h4;
+}
+EXPORT_SYMBOL_GPL(poly1305_core_blocks);
+
+void poly1305_core_emit(const struct poly1305_state *state, void *dst)
+{
+ u32 h0, h1, h2, h3, h4;
+ u32 g0, g1, g2, g3, g4;
+ u32 mask;
+
+ /* fully carry h */
+ h0 = state->h[0];
+ h1 = state->h[1];
+ h2 = state->h[2];
+ h3 = state->h[3];
+ h4 = state->h[4];
+
+ h2 += (h1 >> 26); h1 = h1 & 0x3ffffff;
+ h3 += (h2 >> 26); h2 = h2 & 0x3ffffff;
+ h4 += (h3 >> 26); h3 = h3 & 0x3ffffff;
+ h0 += (h4 >> 26) * 5; h4 = h4 & 0x3ffffff;
+ h1 += (h0 >> 26); h0 = h0 & 0x3ffffff;
+
+ /* compute h + -p */
+ g0 = h0 + 5;
+ g1 = h1 + (g0 >> 26); g0 &= 0x3ffffff;
+ g2 = h2 + (g1 >> 26); g1 &= 0x3ffffff;
+ g3 = h3 + (g2 >> 26); g2 &= 0x3ffffff;
+ g4 = h4 + (g3 >> 26) - (1 << 26); g3 &= 0x3ffffff;
+
+ /* select h if h < p, or h + -p if h >= p */
+ mask = (g4 >> ((sizeof(u32) * 8) - 1)) - 1;
+ g0 &= mask;
+ g1 &= mask;
+ g2 &= mask;
+ g3 &= mask;
+ g4 &= mask;
+ mask = ~mask;
+ h0 = (h0 & mask) | g0;
+ h1 = (h1 & mask) | g1;
+ h2 = (h2 & mask) | g2;
+ h3 = (h3 & mask) | g3;
+ h4 = (h4 & mask) | g4;
+
+ /* h = h % (2^128) */
+ put_unaligned_le32((h0 >> 0) | (h1 << 26), dst + 0);
+ put_unaligned_le32((h1 >> 6) | (h2 << 20), dst + 4);
+ put_unaligned_le32((h2 >> 12) | (h3 << 14), dst + 8);
+ put_unaligned_le32((h3 >> 18) | (h4 << 8), dst + 12);
+}
+EXPORT_SYMBOL_GPL(poly1305_core_emit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");

View File

@@ -1,251 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:20 +0100
Subject: [PATCH] crypto: x86/poly1305 - unify Poly1305 state struct with
generic code
commit ad8f5b88383ea685f2b8df2a12ee3e08089a1287 upstream.
In preparation of exposing a Poly1305 library interface directly from
the accelerated x86 driver, align the state descriptor of the x86 code
with the one used by the generic driver. This is needed to make the
library interface unified between all implementations.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/x86/crypto/poly1305_glue.c | 88 ++++++++++--------------------
crypto/poly1305_generic.c | 6 +-
include/crypto/internal/poly1305.h | 4 +-
include/crypto/poly1305.h | 18 +++---
4 files changed, 43 insertions(+), 73 deletions(-)
--- a/arch/x86/crypto/poly1305_glue.c
+++ b/arch/x86/crypto/poly1305_glue.c
@@ -14,40 +14,14 @@
#include <linux/module.h>
#include <asm/simd.h>
-struct poly1305_simd_desc_ctx {
- struct poly1305_desc_ctx base;
- /* derived key u set? */
- bool uset;
-#ifdef CONFIG_AS_AVX2
- /* derived keys r^3, r^4 set? */
- bool wset;
-#endif
- /* derived Poly1305 key r^2 */
- u32 u[5];
- /* ... silently appended r^3 and r^4 when using AVX2 */
-};
-
asmlinkage void poly1305_block_sse2(u32 *h, const u8 *src,
const u32 *r, unsigned int blocks);
asmlinkage void poly1305_2block_sse2(u32 *h, const u8 *src, const u32 *r,
unsigned int blocks, const u32 *u);
-#ifdef CONFIG_AS_AVX2
asmlinkage void poly1305_4block_avx2(u32 *h, const u8 *src, const u32 *r,
unsigned int blocks, const u32 *u);
-static bool poly1305_use_avx2;
-#endif
-static int poly1305_simd_init(struct shash_desc *desc)
-{
- struct poly1305_simd_desc_ctx *sctx = shash_desc_ctx(desc);
-
- sctx->uset = false;
-#ifdef CONFIG_AS_AVX2
- sctx->wset = false;
-#endif
-
- return crypto_poly1305_init(desc);
-}
+static bool poly1305_use_avx2 __ro_after_init;
static void poly1305_simd_mult(u32 *a, const u32 *b)
{
@@ -63,53 +37,49 @@ static void poly1305_simd_mult(u32 *a, c
static unsigned int poly1305_simd_blocks(struct poly1305_desc_ctx *dctx,
const u8 *src, unsigned int srclen)
{
- struct poly1305_simd_desc_ctx *sctx;
unsigned int blocks, datalen;
- BUILD_BUG_ON(offsetof(struct poly1305_simd_desc_ctx, base));
- sctx = container_of(dctx, struct poly1305_simd_desc_ctx, base);
-
if (unlikely(!dctx->sset)) {
datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
src += srclen - datalen;
srclen = datalen;
}
-#ifdef CONFIG_AS_AVX2
- if (poly1305_use_avx2 && srclen >= POLY1305_BLOCK_SIZE * 4) {
- if (unlikely(!sctx->wset)) {
- if (!sctx->uset) {
- memcpy(sctx->u, dctx->r.r, sizeof(sctx->u));
- poly1305_simd_mult(sctx->u, dctx->r.r);
- sctx->uset = true;
+ if (IS_ENABLED(CONFIG_AS_AVX2) &&
+ poly1305_use_avx2 &&
+ srclen >= POLY1305_BLOCK_SIZE * 4) {
+ if (unlikely(dctx->rset < 4)) {
+ if (dctx->rset < 2) {
+ dctx->r[1] = dctx->r[0];
+ poly1305_simd_mult(dctx->r[1].r, dctx->r[0].r);
}
- memcpy(sctx->u + 5, sctx->u, sizeof(sctx->u));
- poly1305_simd_mult(sctx->u + 5, dctx->r.r);
- memcpy(sctx->u + 10, sctx->u + 5, sizeof(sctx->u));
- poly1305_simd_mult(sctx->u + 10, dctx->r.r);
- sctx->wset = true;
+ dctx->r[2] = dctx->r[1];
+ poly1305_simd_mult(dctx->r[2].r, dctx->r[0].r);
+ dctx->r[3] = dctx->r[2];
+ poly1305_simd_mult(dctx->r[3].r, dctx->r[0].r);
+ dctx->rset = 4;
}
blocks = srclen / (POLY1305_BLOCK_SIZE * 4);
- poly1305_4block_avx2(dctx->h.h, src, dctx->r.r, blocks,
- sctx->u);
+ poly1305_4block_avx2(dctx->h.h, src, dctx->r[0].r, blocks,
+ dctx->r[1].r);
src += POLY1305_BLOCK_SIZE * 4 * blocks;
srclen -= POLY1305_BLOCK_SIZE * 4 * blocks;
}
-#endif
+
if (likely(srclen >= POLY1305_BLOCK_SIZE * 2)) {
- if (unlikely(!sctx->uset)) {
- memcpy(sctx->u, dctx->r.r, sizeof(sctx->u));
- poly1305_simd_mult(sctx->u, dctx->r.r);
- sctx->uset = true;
+ if (unlikely(dctx->rset < 2)) {
+ dctx->r[1] = dctx->r[0];
+ poly1305_simd_mult(dctx->r[1].r, dctx->r[0].r);
+ dctx->rset = 2;
}
blocks = srclen / (POLY1305_BLOCK_SIZE * 2);
- poly1305_2block_sse2(dctx->h.h, src, dctx->r.r, blocks,
- sctx->u);
+ poly1305_2block_sse2(dctx->h.h, src, dctx->r[0].r,
+ blocks, dctx->r[1].r);
src += POLY1305_BLOCK_SIZE * 2 * blocks;
srclen -= POLY1305_BLOCK_SIZE * 2 * blocks;
}
if (srclen >= POLY1305_BLOCK_SIZE) {
- poly1305_block_sse2(dctx->h.h, src, dctx->r.r, 1);
+ poly1305_block_sse2(dctx->h.h, src, dctx->r[0].r, 1);
srclen -= POLY1305_BLOCK_SIZE;
}
return srclen;
@@ -159,10 +129,10 @@ static int poly1305_simd_update(struct s
static struct shash_alg alg = {
.digestsize = POLY1305_DIGEST_SIZE,
- .init = poly1305_simd_init,
+ .init = crypto_poly1305_init,
.update = poly1305_simd_update,
.final = crypto_poly1305_final,
- .descsize = sizeof(struct poly1305_simd_desc_ctx),
+ .descsize = sizeof(struct poly1305_desc_ctx),
.base = {
.cra_name = "poly1305",
.cra_driver_name = "poly1305-simd",
@@ -177,14 +147,14 @@ static int __init poly1305_simd_mod_init
if (!boot_cpu_has(X86_FEATURE_XMM2))
return -ENODEV;
-#ifdef CONFIG_AS_AVX2
- poly1305_use_avx2 = boot_cpu_has(X86_FEATURE_AVX) &&
+ poly1305_use_avx2 = IS_ENABLED(CONFIG_AS_AVX2) &&
+ boot_cpu_has(X86_FEATURE_AVX) &&
boot_cpu_has(X86_FEATURE_AVX2) &&
cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL);
- alg.descsize = sizeof(struct poly1305_simd_desc_ctx);
+ alg.descsize = sizeof(struct poly1305_desc_ctx) + 5 * sizeof(u32);
if (poly1305_use_avx2)
alg.descsize += 10 * sizeof(u32);
-#endif
+
return crypto_register_shash(&alg);
}
--- a/crypto/poly1305_generic.c
+++ b/crypto/poly1305_generic.c
@@ -25,7 +25,7 @@ int crypto_poly1305_init(struct shash_de
poly1305_core_init(&dctx->h);
dctx->buflen = 0;
- dctx->rset = false;
+ dctx->rset = 0;
dctx->sset = false;
return 0;
@@ -43,7 +43,7 @@ static void poly1305_blocks(struct poly1
srclen = datalen;
}
- poly1305_core_blocks(&dctx->h, &dctx->r, src,
+ poly1305_core_blocks(&dctx->h, dctx->r, src,
srclen / POLY1305_BLOCK_SIZE, 1);
}
@@ -95,7 +95,7 @@ int crypto_poly1305_final(struct shash_d
dctx->buf[dctx->buflen++] = 1;
memset(dctx->buf + dctx->buflen, 0,
POLY1305_BLOCK_SIZE - dctx->buflen);
- poly1305_core_blocks(&dctx->h, &dctx->r, dctx->buf, 1, 0);
+ poly1305_core_blocks(&dctx->h, dctx->r, dctx->buf, 1, 0);
}
poly1305_core_emit(&dctx->h, digest);
--- a/include/crypto/internal/poly1305.h
+++ b/include/crypto/internal/poly1305.h
@@ -46,10 +46,10 @@ unsigned int crypto_poly1305_setdesckey(
{
if (!dctx->sset) {
if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) {
- poly1305_core_setkey(&dctx->r, src);
+ poly1305_core_setkey(dctx->r, src);
src += POLY1305_BLOCK_SIZE;
srclen -= POLY1305_BLOCK_SIZE;
- dctx->rset = true;
+ dctx->rset = 1;
}
if (srclen >= POLY1305_BLOCK_SIZE) {
dctx->s[0] = get_unaligned_le32(src + 0);
--- a/include/crypto/poly1305.h
+++ b/include/crypto/poly1305.h
@@ -22,20 +22,20 @@ struct poly1305_state {
};
struct poly1305_desc_ctx {
- /* key */
- struct poly1305_key r;
- /* finalize key */
- u32 s[4];
- /* accumulator */
- struct poly1305_state h;
/* partial buffer */
u8 buf[POLY1305_BLOCK_SIZE];
/* bytes used in partial buffer */
unsigned int buflen;
- /* r key has been set */
- bool rset;
- /* s key has been set */
+ /* how many keys have been set in r[] */
+ unsigned short rset;
+ /* whether s[] has been set */
bool sset;
+ /* finalize key */
+ u32 s[4];
+ /* accumulator */
+ struct poly1305_state h;
+ /* key */
+ struct poly1305_key r[1];
};
#endif

View File

@@ -1,224 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:21 +0100
Subject: [PATCH] crypto: poly1305 - expose init/update/final library interface
commit a1d93064094cc5e24d64e35cf093e7191d0c9344 upstream.
Expose the existing generic Poly1305 code via a init/update/final
library interface so that callers are not required to go through
the crypto API's shash abstraction to access it. At the same time,
make some preparations so that the library implementation can be
superseded by an accelerated arch-specific version in the future.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
crypto/poly1305_generic.c | 22 +-----------
include/crypto/poly1305.h | 38 +++++++++++++++++++-
lib/crypto/Kconfig | 26 ++++++++++++++
lib/crypto/poly1305.c | 74 +++++++++++++++++++++++++++++++++++++++
4 files changed, 138 insertions(+), 22 deletions(-)
--- a/crypto/poly1305_generic.c
+++ b/crypto/poly1305_generic.c
@@ -85,31 +85,11 @@ EXPORT_SYMBOL_GPL(crypto_poly1305_update
int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
- __le32 digest[4];
- u64 f = 0;
if (unlikely(!dctx->sset))
return -ENOKEY;
- if (unlikely(dctx->buflen)) {
- dctx->buf[dctx->buflen++] = 1;
- memset(dctx->buf + dctx->buflen, 0,
- POLY1305_BLOCK_SIZE - dctx->buflen);
- poly1305_core_blocks(&dctx->h, dctx->r, dctx->buf, 1, 0);
- }
-
- poly1305_core_emit(&dctx->h, digest);
-
- /* mac = (h + s) % (2^128) */
- f = (f >> 32) + le32_to_cpu(digest[0]) + dctx->s[0];
- put_unaligned_le32(f, dst + 0);
- f = (f >> 32) + le32_to_cpu(digest[1]) + dctx->s[1];
- put_unaligned_le32(f, dst + 4);
- f = (f >> 32) + le32_to_cpu(digest[2]) + dctx->s[2];
- put_unaligned_le32(f, dst + 8);
- f = (f >> 32) + le32_to_cpu(digest[3]) + dctx->s[3];
- put_unaligned_le32(f, dst + 12);
-
+ poly1305_final_generic(dctx, dst);
return 0;
}
EXPORT_SYMBOL_GPL(crypto_poly1305_final);
--- a/include/crypto/poly1305.h
+++ b/include/crypto/poly1305.h
@@ -35,7 +35,43 @@ struct poly1305_desc_ctx {
/* accumulator */
struct poly1305_state h;
/* key */
- struct poly1305_key r[1];
+ struct poly1305_key r[CONFIG_CRYPTO_LIB_POLY1305_RSIZE];
};
+void poly1305_init_arch(struct poly1305_desc_ctx *desc, const u8 *key);
+void poly1305_init_generic(struct poly1305_desc_ctx *desc, const u8 *key);
+
+static inline void poly1305_init(struct poly1305_desc_ctx *desc, const u8 *key)
+{
+ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
+ poly1305_init_arch(desc, key);
+ else
+ poly1305_init_generic(desc, key);
+}
+
+void poly1305_update_arch(struct poly1305_desc_ctx *desc, const u8 *src,
+ unsigned int nbytes);
+void poly1305_update_generic(struct poly1305_desc_ctx *desc, const u8 *src,
+ unsigned int nbytes);
+
+static inline void poly1305_update(struct poly1305_desc_ctx *desc,
+ const u8 *src, unsigned int nbytes)
+{
+ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
+ poly1305_update_arch(desc, src, nbytes);
+ else
+ poly1305_update_generic(desc, src, nbytes);
+}
+
+void poly1305_final_arch(struct poly1305_desc_ctx *desc, u8 *digest);
+void poly1305_final_generic(struct poly1305_desc_ctx *desc, u8 *digest);
+
+static inline void poly1305_final(struct poly1305_desc_ctx *desc, u8 *digest)
+{
+ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
+ poly1305_final_arch(desc, digest);
+ else
+ poly1305_final_generic(desc, digest);
+}
+
#endif
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -37,8 +37,34 @@ config CRYPTO_LIB_CHACHA
config CRYPTO_LIB_DES
tristate
+config CRYPTO_LIB_POLY1305_RSIZE
+ int
+ default 1
+
+config CRYPTO_ARCH_HAVE_LIB_POLY1305
+ tristate
+ help
+ Declares whether the architecture provides an arch-specific
+ accelerated implementation of the Poly1305 library interface,
+ either builtin or as a module.
+
config CRYPTO_LIB_POLY1305_GENERIC
tristate
+ help
+ This symbol can be depended upon by arch implementations of the
+ Poly1305 library interface that require the generic code as a
+ fallback, e.g., for SIMD implementations. If no arch specific
+ implementation is enabled, this implementation serves the users
+ of CRYPTO_LIB_POLY1305.
+
+config CRYPTO_LIB_POLY1305
+ tristate "Poly1305 library interface"
+ depends on CRYPTO_ARCH_HAVE_LIB_POLY1305 || !CRYPTO_ARCH_HAVE_LIB_POLY1305
+ select CRYPTO_LIB_POLY1305_GENERIC if CRYPTO_ARCH_HAVE_LIB_POLY1305=n
+ help
+ Enable the Poly1305 library interface. This interface may be fulfilled
+ by either the generic implementation or an arch-specific one, if one
+ is available and enabled.
config CRYPTO_LIB_SHA256
tristate
--- a/lib/crypto/poly1305.c
+++ b/lib/crypto/poly1305.c
@@ -154,5 +154,79 @@ void poly1305_core_emit(const struct pol
}
EXPORT_SYMBOL_GPL(poly1305_core_emit);
+void poly1305_init_generic(struct poly1305_desc_ctx *desc, const u8 *key)
+{
+ poly1305_core_setkey(desc->r, key);
+ desc->s[0] = get_unaligned_le32(key + 16);
+ desc->s[1] = get_unaligned_le32(key + 20);
+ desc->s[2] = get_unaligned_le32(key + 24);
+ desc->s[3] = get_unaligned_le32(key + 28);
+ poly1305_core_init(&desc->h);
+ desc->buflen = 0;
+ desc->sset = true;
+ desc->rset = 1;
+}
+EXPORT_SYMBOL_GPL(poly1305_init_generic);
+
+void poly1305_update_generic(struct poly1305_desc_ctx *desc, const u8 *src,
+ unsigned int nbytes)
+{
+ unsigned int bytes;
+
+ if (unlikely(desc->buflen)) {
+ bytes = min(nbytes, POLY1305_BLOCK_SIZE - desc->buflen);
+ memcpy(desc->buf + desc->buflen, src, bytes);
+ src += bytes;
+ nbytes -= bytes;
+ desc->buflen += bytes;
+
+ if (desc->buflen == POLY1305_BLOCK_SIZE) {
+ poly1305_core_blocks(&desc->h, desc->r, desc->buf, 1, 1);
+ desc->buflen = 0;
+ }
+ }
+
+ if (likely(nbytes >= POLY1305_BLOCK_SIZE)) {
+ poly1305_core_blocks(&desc->h, desc->r, src,
+ nbytes / POLY1305_BLOCK_SIZE, 1);
+ src += nbytes - (nbytes % POLY1305_BLOCK_SIZE);
+ nbytes %= POLY1305_BLOCK_SIZE;
+ }
+
+ if (unlikely(nbytes)) {
+ desc->buflen = nbytes;
+ memcpy(desc->buf, src, nbytes);
+ }
+}
+EXPORT_SYMBOL_GPL(poly1305_update_generic);
+
+void poly1305_final_generic(struct poly1305_desc_ctx *desc, u8 *dst)
+{
+ __le32 digest[4];
+ u64 f = 0;
+
+ if (unlikely(desc->buflen)) {
+ desc->buf[desc->buflen++] = 1;
+ memset(desc->buf + desc->buflen, 0,
+ POLY1305_BLOCK_SIZE - desc->buflen);
+ poly1305_core_blocks(&desc->h, desc->r, desc->buf, 1, 0);
+ }
+
+ poly1305_core_emit(&desc->h, digest);
+
+ /* mac = (h + s) % (2^128) */
+ f = (f >> 32) + le32_to_cpu(digest[0]) + desc->s[0];
+ put_unaligned_le32(f, dst + 0);
+ f = (f >> 32) + le32_to_cpu(digest[1]) + desc->s[1];
+ put_unaligned_le32(f, dst + 4);
+ f = (f >> 32) + le32_to_cpu(digest[2]) + desc->s[2];
+ put_unaligned_le32(f, dst + 8);
+ f = (f >> 32) + le32_to_cpu(digest[3]) + desc->s[3];
+ put_unaligned_le32(f, dst + 12);
+
+ *desc = (struct poly1305_desc_ctx){};
+}
+EXPORT_SYMBOL_GPL(poly1305_final_generic);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");

View File

@@ -1,217 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:22 +0100
Subject: [PATCH] crypto: x86/poly1305 - depend on generic library not generic
shash
commit 1b2c6a5120489d41c8ea3b8dacd0b4586289b158 upstream.
Remove the dependency on the generic Poly1305 driver. Instead, depend
on the generic library so that we only reuse code without pulling in
the generic skcipher implementation as well.
While at it, remove the logic that prefers the non-SIMD path for short
inputs - this is no longer necessary after recent FPU handling changes
on x86.
Since this removes the last remaining user of the routines exported
by the generic shash driver, unexport them and make them static.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/x86/crypto/poly1305_glue.c | 66 +++++++++++++++++++++++++-----
crypto/Kconfig | 2 +-
crypto/poly1305_generic.c | 11 ++---
include/crypto/internal/poly1305.h | 9 ----
4 files changed, 60 insertions(+), 28 deletions(-)
--- a/arch/x86/crypto/poly1305_glue.c
+++ b/arch/x86/crypto/poly1305_glue.c
@@ -34,6 +34,24 @@ static void poly1305_simd_mult(u32 *a, c
poly1305_block_sse2(a, m, b, 1);
}
+static unsigned int poly1305_scalar_blocks(struct poly1305_desc_ctx *dctx,
+ const u8 *src, unsigned int srclen)
+{
+ unsigned int datalen;
+
+ if (unlikely(!dctx->sset)) {
+ datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
+ src += srclen - datalen;
+ srclen = datalen;
+ }
+ if (srclen >= POLY1305_BLOCK_SIZE) {
+ poly1305_core_blocks(&dctx->h, dctx->r, src,
+ srclen / POLY1305_BLOCK_SIZE, 1);
+ srclen %= POLY1305_BLOCK_SIZE;
+ }
+ return srclen;
+}
+
static unsigned int poly1305_simd_blocks(struct poly1305_desc_ctx *dctx,
const u8 *src, unsigned int srclen)
{
@@ -91,12 +109,6 @@ static int poly1305_simd_update(struct s
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
unsigned int bytes;
- /* kernel_fpu_begin/end is costly, use fallback for small updates */
- if (srclen <= 288 || !crypto_simd_usable())
- return crypto_poly1305_update(desc, src, srclen);
-
- kernel_fpu_begin();
-
if (unlikely(dctx->buflen)) {
bytes = min(srclen, POLY1305_BLOCK_SIZE - dctx->buflen);
memcpy(dctx->buf + dctx->buflen, src, bytes);
@@ -105,25 +117,57 @@ static int poly1305_simd_update(struct s
dctx->buflen += bytes;
if (dctx->buflen == POLY1305_BLOCK_SIZE) {
- poly1305_simd_blocks(dctx, dctx->buf,
- POLY1305_BLOCK_SIZE);
+ if (likely(crypto_simd_usable())) {
+ kernel_fpu_begin();
+ poly1305_simd_blocks(dctx, dctx->buf,
+ POLY1305_BLOCK_SIZE);
+ kernel_fpu_end();
+ } else {
+ poly1305_scalar_blocks(dctx, dctx->buf,
+ POLY1305_BLOCK_SIZE);
+ }
dctx->buflen = 0;
}
}
if (likely(srclen >= POLY1305_BLOCK_SIZE)) {
- bytes = poly1305_simd_blocks(dctx, src, srclen);
+ if (likely(crypto_simd_usable())) {
+ kernel_fpu_begin();
+ bytes = poly1305_simd_blocks(dctx, src, srclen);
+ kernel_fpu_end();
+ } else {
+ bytes = poly1305_scalar_blocks(dctx, src, srclen);
+ }
src += srclen - bytes;
srclen = bytes;
}
- kernel_fpu_end();
-
if (unlikely(srclen)) {
dctx->buflen = srclen;
memcpy(dctx->buf, src, srclen);
}
+}
+
+static int crypto_poly1305_init(struct shash_desc *desc)
+{
+ struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
+
+ poly1305_core_init(&dctx->h);
+ dctx->buflen = 0;
+ dctx->rset = 0;
+ dctx->sset = false;
+
+ return 0;
+}
+
+static int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
+{
+ struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
+
+ if (unlikely(!dctx->sset))
+ return -ENOKEY;
+ poly1305_final_generic(dctx, dst);
return 0;
}
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -697,7 +697,7 @@ config CRYPTO_POLY1305
config CRYPTO_POLY1305_X86_64
tristate "Poly1305 authenticator algorithm (x86_64/SSE2/AVX2)"
depends on X86 && 64BIT
- select CRYPTO_POLY1305
+ select CRYPTO_LIB_POLY1305_GENERIC
help
Poly1305 authenticator algorithm, RFC7539.
--- a/crypto/poly1305_generic.c
+++ b/crypto/poly1305_generic.c
@@ -19,7 +19,7 @@
#include <linux/module.h>
#include <asm/unaligned.h>
-int crypto_poly1305_init(struct shash_desc *desc)
+static int crypto_poly1305_init(struct shash_desc *desc)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
@@ -30,7 +30,6 @@ int crypto_poly1305_init(struct shash_de
return 0;
}
-EXPORT_SYMBOL_GPL(crypto_poly1305_init);
static void poly1305_blocks(struct poly1305_desc_ctx *dctx, const u8 *src,
unsigned int srclen)
@@ -47,8 +46,8 @@ static void poly1305_blocks(struct poly1
srclen / POLY1305_BLOCK_SIZE, 1);
}
-int crypto_poly1305_update(struct shash_desc *desc,
- const u8 *src, unsigned int srclen)
+static int crypto_poly1305_update(struct shash_desc *desc,
+ const u8 *src, unsigned int srclen)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
unsigned int bytes;
@@ -80,9 +79,8 @@ int crypto_poly1305_update(struct shash_
return 0;
}
-EXPORT_SYMBOL_GPL(crypto_poly1305_update);
-int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
+static int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
@@ -92,7 +90,6 @@ int crypto_poly1305_final(struct shash_d
poly1305_final_generic(dctx, dst);
return 0;
}
-EXPORT_SYMBOL_GPL(crypto_poly1305_final);
static struct shash_alg poly1305_alg = {
.digestsize = POLY1305_DIGEST_SIZE,
--- a/include/crypto/internal/poly1305.h
+++ b/include/crypto/internal/poly1305.h
@@ -10,8 +10,6 @@
#include <linux/types.h>
#include <crypto/poly1305.h>
-struct shash_desc;
-
/*
* Poly1305 core functions. These implement the ε-almost-∆-universal hash
* function underlying the Poly1305 MAC, i.e. they don't add an encrypted nonce
@@ -28,13 +26,6 @@ void poly1305_core_blocks(struct poly130
unsigned int nblocks, u32 hibit);
void poly1305_core_emit(const struct poly1305_state *state, void *dst);
-/* Crypto API helper functions for the Poly1305 MAC */
-int crypto_poly1305_init(struct shash_desc *desc);
-
-int crypto_poly1305_update(struct shash_desc *desc,
- const u8 *src, unsigned int srclen);
-int crypto_poly1305_final(struct shash_desc *desc, u8 *dst);
-
/*
* Poly1305 requires a unique key for each tag, which implies that we can't set
* it on the tfm that gets accessed by multiple users simultaneously. Instead we

View File

@@ -1,163 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:23 +0100
Subject: [PATCH] crypto: x86/poly1305 - expose existing driver as poly1305
library
commit f0e89bcfbb894e5844cd1bbf6b3cf7c63cb0f5ac upstream.
Implement the arch init/update/final Poly1305 library routines in the
accelerated SIMD driver for x86 so they are accessible to users of
the Poly1305 library interface as well.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
arch/x86/crypto/poly1305_glue.c | 57 ++++++++++++++++++++++++---------
crypto/Kconfig | 1 +
lib/crypto/Kconfig | 1 +
3 files changed, 43 insertions(+), 16 deletions(-)
--- a/arch/x86/crypto/poly1305_glue.c
+++ b/arch/x86/crypto/poly1305_glue.c
@@ -10,6 +10,7 @@
#include <crypto/internal/poly1305.h>
#include <crypto/internal/simd.h>
#include <linux/crypto.h>
+#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/simd.h>
@@ -21,7 +22,8 @@ asmlinkage void poly1305_2block_sse2(u32
asmlinkage void poly1305_4block_avx2(u32 *h, const u8 *src, const u32 *r,
unsigned int blocks, const u32 *u);
-static bool poly1305_use_avx2 __ro_after_init;
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(poly1305_use_simd);
+static __ro_after_init DEFINE_STATIC_KEY_FALSE(poly1305_use_avx2);
static void poly1305_simd_mult(u32 *a, const u32 *b)
{
@@ -64,7 +66,7 @@ static unsigned int poly1305_simd_blocks
}
if (IS_ENABLED(CONFIG_AS_AVX2) &&
- poly1305_use_avx2 &&
+ static_branch_likely(&poly1305_use_avx2) &&
srclen >= POLY1305_BLOCK_SIZE * 4) {
if (unlikely(dctx->rset < 4)) {
if (dctx->rset < 2) {
@@ -103,10 +105,15 @@ static unsigned int poly1305_simd_blocks
return srclen;
}
-static int poly1305_simd_update(struct shash_desc *desc,
- const u8 *src, unsigned int srclen)
+void poly1305_init_arch(struct poly1305_desc_ctx *desc, const u8 *key)
+{
+ poly1305_init_generic(desc, key);
+}
+EXPORT_SYMBOL(poly1305_init_arch);
+
+void poly1305_update_arch(struct poly1305_desc_ctx *dctx, const u8 *src,
+ unsigned int srclen)
{
- struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
unsigned int bytes;
if (unlikely(dctx->buflen)) {
@@ -117,7 +124,8 @@ static int poly1305_simd_update(struct s
dctx->buflen += bytes;
if (dctx->buflen == POLY1305_BLOCK_SIZE) {
- if (likely(crypto_simd_usable())) {
+ if (static_branch_likely(&poly1305_use_simd) &&
+ likely(crypto_simd_usable())) {
kernel_fpu_begin();
poly1305_simd_blocks(dctx, dctx->buf,
POLY1305_BLOCK_SIZE);
@@ -131,7 +139,8 @@ static int poly1305_simd_update(struct s
}
if (likely(srclen >= POLY1305_BLOCK_SIZE)) {
- if (likely(crypto_simd_usable())) {
+ if (static_branch_likely(&poly1305_use_simd) &&
+ likely(crypto_simd_usable())) {
kernel_fpu_begin();
bytes = poly1305_simd_blocks(dctx, src, srclen);
kernel_fpu_end();
@@ -147,6 +156,13 @@ static int poly1305_simd_update(struct s
memcpy(dctx->buf, src, srclen);
}
}
+EXPORT_SYMBOL(poly1305_update_arch);
+
+void poly1305_final_arch(struct poly1305_desc_ctx *desc, u8 *digest)
+{
+ poly1305_final_generic(desc, digest);
+}
+EXPORT_SYMBOL(poly1305_final_arch);
static int crypto_poly1305_init(struct shash_desc *desc)
{
@@ -171,6 +187,15 @@ static int crypto_poly1305_final(struct
return 0;
}
+static int poly1305_simd_update(struct shash_desc *desc,
+ const u8 *src, unsigned int srclen)
+{
+ struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
+
+ poly1305_update_arch(dctx, src, srclen);
+ return 0;
+}
+
static struct shash_alg alg = {
.digestsize = POLY1305_DIGEST_SIZE,
.init = crypto_poly1305_init,
@@ -189,15 +214,15 @@ static struct shash_alg alg = {
static int __init poly1305_simd_mod_init(void)
{
if (!boot_cpu_has(X86_FEATURE_XMM2))
- return -ENODEV;
+ return 0;
- poly1305_use_avx2 = IS_ENABLED(CONFIG_AS_AVX2) &&
- boot_cpu_has(X86_FEATURE_AVX) &&
- boot_cpu_has(X86_FEATURE_AVX2) &&
- cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL);
- alg.descsize = sizeof(struct poly1305_desc_ctx) + 5 * sizeof(u32);
- if (poly1305_use_avx2)
- alg.descsize += 10 * sizeof(u32);
+ static_branch_enable(&poly1305_use_simd);
+
+ if (IS_ENABLED(CONFIG_AS_AVX2) &&
+ boot_cpu_has(X86_FEATURE_AVX) &&
+ boot_cpu_has(X86_FEATURE_AVX2) &&
+ cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL))
+ static_branch_enable(&poly1305_use_avx2);
return crypto_register_shash(&alg);
}
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -698,6 +698,7 @@ config CRYPTO_POLY1305_X86_64
tristate "Poly1305 authenticator algorithm (x86_64/SSE2/AVX2)"
depends on X86 && 64BIT
select CRYPTO_LIB_POLY1305_GENERIC
+ select CRYPTO_ARCH_HAVE_LIB_POLY1305
help
Poly1305 authenticator algorithm, RFC7539.
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -39,6 +39,7 @@ config CRYPTO_LIB_DES
config CRYPTO_LIB_POLY1305_RSIZE
int
+ default 4 if X86_64
default 1
config CRYPTO_ARCH_HAVE_LIB_POLY1305

View File

@@ -1,322 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Fri, 8 Nov 2019 13:22:29 +0100
Subject: [PATCH] crypto: testmgr - add test cases for Blake2s
commit 17e1df67023a5c9ccaeb5de8bf5b88f63127ecf7 upstream.
As suggested by Eric for the Blake2b implementation contributed by
David, introduce a set of test vectors for Blake2s covering different
digest and key sizes.
blake2s-128 blake2s-160 blake2s-224 blake2s-256
---------------------------------------------------
len=0 | klen=0 klen=1 klen=16 klen=32
len=1 | klen=16 klen=32 klen=0 klen=1
len=7 | klen=32 klen=0 klen=1 klen=16
len=15 | klen=1 klen=16 klen=32 klen=0
len=64 | klen=0 klen=1 klen=16 klen=32
len=247 | klen=16 klen=32 klen=0 klen=1
len=256 | klen=32 klen=0 klen=1 klen=16
Cc: David Sterba <dsterba@suse.com>
Cc: Eric Biggers <ebiggers@google.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
crypto/testmgr.c | 24 +++++
crypto/testmgr.h | 251 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 275 insertions(+)
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4035,6 +4035,30 @@ static const struct alg_test_desc alg_te
.test = alg_test_null,
.fips_allowed = 1,
}, {
+ .alg = "blake2s-128",
+ .test = alg_test_hash,
+ .suite = {
+ .hash = __VECS(blakes2s_128_tv_template)
+ }
+ }, {
+ .alg = "blake2s-160",
+ .test = alg_test_hash,
+ .suite = {
+ .hash = __VECS(blakes2s_160_tv_template)
+ }
+ }, {
+ .alg = "blake2s-224",
+ .test = alg_test_hash,
+ .suite = {
+ .hash = __VECS(blakes2s_224_tv_template)
+ }
+ }, {
+ .alg = "blake2s-256",
+ .test = alg_test_hash,
+ .suite = {
+ .hash = __VECS(blakes2s_256_tv_template)
+ }
+ }, {
.alg = "cbc(aes)",
.test = alg_test_skcipher,
.fips_allowed = 1,
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -31567,4 +31567,255 @@ static const struct aead_testvec essiv_h
},
};
+static const char blake2_ordered_sequence[] =
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "\x20\x21\x22\x23\x24\x25\x26\x27"
+ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+ "\x30\x31\x32\x33\x34\x35\x36\x37"
+ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+ "\x40\x41\x42\x43\x44\x45\x46\x47"
+ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+ "\x50\x51\x52\x53\x54\x55\x56\x57"
+ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+ "\x60\x61\x62\x63\x64\x65\x66\x67"
+ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+ "\x70\x71\x72\x73\x74\x75\x76\x77"
+ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+ "\x80\x81\x82\x83\x84\x85\x86\x87"
+ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
+
+static const struct hash_testvec blakes2s_128_tv_template[] = {{
+ .digest = (u8[]){ 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01,
+ 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c, },
+}, {
+ .plaintext = blake2_ordered_sequence,
+ .psize = 64,
+ .digest = (u8[]){ 0xdc, 0x66, 0xca, 0x8f, 0x03, 0x86, 0x58, 0x01,
+ 0xb0, 0xff, 0xe0, 0x6e, 0xd8, 0xa1, 0xa9, 0x0e, },
+}, {
+ .ksize = 16,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 1,
+ .digest = (u8[]){ 0x88, 0x1e, 0x42, 0xe7, 0xbb, 0x35, 0x80, 0x82,
+ 0x63, 0x7c, 0x0a, 0x0f, 0xd7, 0xec, 0x6c, 0x2f, },
+}, {
+ .ksize = 32,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 7,
+ .digest = (u8[]){ 0xcf, 0x9e, 0x07, 0x2a, 0xd5, 0x22, 0xf2, 0xcd,
+ 0xa2, 0xd8, 0x25, 0x21, 0x80, 0x86, 0x73, 0x1c, },
+}, {
+ .ksize = 1,
+ .key = "B",
+ .plaintext = blake2_ordered_sequence,
+ .psize = 15,
+ .digest = (u8[]){ 0xf6, 0x33, 0x5a, 0x2c, 0x22, 0xa0, 0x64, 0xb2,
+ 0xb6, 0x3f, 0xeb, 0xbc, 0xd1, 0xc3, 0xe5, 0xb2, },
+}, {
+ .ksize = 16,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 247,
+ .digest = (u8[]){ 0x72, 0x66, 0x49, 0x60, 0xf9, 0x4a, 0xea, 0xbe,
+ 0x1f, 0xf4, 0x60, 0xce, 0xb7, 0x81, 0xcb, 0x09, },
+}, {
+ .ksize = 32,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 256,
+ .digest = (u8[]){ 0xd5, 0xa4, 0x0e, 0xc3, 0x16, 0xc7, 0x51, 0xa6,
+ 0x3c, 0xd0, 0xd9, 0x11, 0x57, 0xfa, 0x1e, 0xbb, },
+}};
+
+static const struct hash_testvec blakes2s_160_tv_template[] = {{
+ .plaintext = blake2_ordered_sequence,
+ .psize = 7,
+ .digest = (u8[]){ 0xb4, 0xf2, 0x03, 0x49, 0x37, 0xed, 0xb1, 0x3e,
+ 0x5b, 0x2a, 0xca, 0x64, 0x82, 0x74, 0xf6, 0x62,
+ 0xe3, 0xf2, 0x84, 0xff, },
+}, {
+ .plaintext = blake2_ordered_sequence,
+ .psize = 256,
+ .digest = (u8[]){ 0xaa, 0x56, 0x9b, 0xdc, 0x98, 0x17, 0x75, 0xf2,
+ 0xb3, 0x68, 0x83, 0xb7, 0x9b, 0x8d, 0x48, 0xb1,
+ 0x9b, 0x2d, 0x35, 0x05, },
+}, {
+ .ksize = 1,
+ .key = "B",
+ .digest = (u8[]){ 0x50, 0x16, 0xe7, 0x0c, 0x01, 0xd0, 0xd3, 0xc3,
+ 0xf4, 0x3e, 0xb1, 0x6e, 0x97, 0xa9, 0x4e, 0xd1,
+ 0x79, 0x65, 0x32, 0x93, },
+}, {
+ .ksize = 32,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 1,
+ .digest = (u8[]){ 0x1c, 0x2b, 0xcd, 0x9a, 0x68, 0xca, 0x8c, 0x71,
+ 0x90, 0x29, 0x6c, 0x54, 0xfa, 0x56, 0x4a, 0xef,
+ 0xa2, 0x3a, 0x56, 0x9c, },
+}, {
+ .ksize = 16,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 15,
+ .digest = (u8[]){ 0x36, 0xc3, 0x5f, 0x9a, 0xdc, 0x7e, 0xbf, 0x19,
+ 0x68, 0xaa, 0xca, 0xd8, 0x81, 0xbf, 0x09, 0x34,
+ 0x83, 0x39, 0x0f, 0x30, },
+}, {
+ .ksize = 1,
+ .key = "B",
+ .plaintext = blake2_ordered_sequence,
+ .psize = 64,
+ .digest = (u8[]){ 0x86, 0x80, 0x78, 0xa4, 0x14, 0xec, 0x03, 0xe5,
+ 0xb6, 0x9a, 0x52, 0x0e, 0x42, 0xee, 0x39, 0x9d,
+ 0xac, 0xa6, 0x81, 0x63, },
+}, {
+ .ksize = 32,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 247,
+ .digest = (u8[]){ 0x2d, 0xd8, 0xd2, 0x53, 0x66, 0xfa, 0xa9, 0x01,
+ 0x1c, 0x9c, 0xaf, 0xa3, 0xe2, 0x9d, 0x9b, 0x10,
+ 0x0a, 0xf6, 0x73, 0xe8, },
+}};
+
+static const struct hash_testvec blakes2s_224_tv_template[] = {{
+ .plaintext = blake2_ordered_sequence,
+ .psize = 1,
+ .digest = (u8[]){ 0x61, 0xb9, 0x4e, 0xc9, 0x46, 0x22, 0xa3, 0x91,
+ 0xd2, 0xae, 0x42, 0xe6, 0x45, 0x6c, 0x90, 0x12,
+ 0xd5, 0x80, 0x07, 0x97, 0xb8, 0x86, 0x5a, 0xfc,
+ 0x48, 0x21, 0x97, 0xbb, },
+}, {
+ .plaintext = blake2_ordered_sequence,
+ .psize = 247,
+ .digest = (u8[]){ 0x9e, 0xda, 0xc7, 0x20, 0x2c, 0xd8, 0x48, 0x2e,
+ 0x31, 0x94, 0xab, 0x46, 0x6d, 0x94, 0xd8, 0xb4,
+ 0x69, 0xcd, 0xae, 0x19, 0x6d, 0x9e, 0x41, 0xcc,
+ 0x2b, 0xa4, 0xd5, 0xf6, },
+}, {
+ .ksize = 16,
+ .key = blake2_ordered_sequence,
+ .digest = (u8[]){ 0x32, 0xc0, 0xac, 0xf4, 0x3b, 0xd3, 0x07, 0x9f,
+ 0xbe, 0xfb, 0xfa, 0x4d, 0x6b, 0x4e, 0x56, 0xb3,
+ 0xaa, 0xd3, 0x27, 0xf6, 0x14, 0xbf, 0xb9, 0x32,
+ 0xa7, 0x19, 0xfc, 0xb8, },
+}, {
+ .ksize = 1,
+ .key = "B",
+ .plaintext = blake2_ordered_sequence,
+ .psize = 7,
+ .digest = (u8[]){ 0x73, 0xad, 0x5e, 0x6d, 0xb9, 0x02, 0x8e, 0x76,
+ 0xf2, 0x66, 0x42, 0x4b, 0x4c, 0xfa, 0x1f, 0xe6,
+ 0x2e, 0x56, 0x40, 0xe5, 0xa2, 0xb0, 0x3c, 0xe8,
+ 0x7b, 0x45, 0xfe, 0x05, },
+}, {
+ .ksize = 32,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 15,
+ .digest = (u8[]){ 0x16, 0x60, 0xfb, 0x92, 0x54, 0xb3, 0x6e, 0x36,
+ 0x81, 0xf4, 0x16, 0x41, 0xc3, 0x3d, 0xd3, 0x43,
+ 0x84, 0xed, 0x10, 0x6f, 0x65, 0x80, 0x7a, 0x3e,
+ 0x25, 0xab, 0xc5, 0x02, },
+}, {
+ .ksize = 16,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 64,
+ .digest = (u8[]){ 0xca, 0xaa, 0x39, 0x67, 0x9c, 0xf7, 0x6b, 0xc7,
+ 0xb6, 0x82, 0xca, 0x0e, 0x65, 0x36, 0x5b, 0x7c,
+ 0x24, 0x00, 0xfa, 0x5f, 0xda, 0x06, 0x91, 0x93,
+ 0x6a, 0x31, 0x83, 0xb5, },
+}, {
+ .ksize = 1,
+ .key = "B",
+ .plaintext = blake2_ordered_sequence,
+ .psize = 256,
+ .digest = (u8[]){ 0x90, 0x02, 0x26, 0xb5, 0x06, 0x9c, 0x36, 0x86,
+ 0x94, 0x91, 0x90, 0x1e, 0x7d, 0x2a, 0x71, 0xb2,
+ 0x48, 0xb5, 0xe8, 0x16, 0xfd, 0x64, 0x33, 0x45,
+ 0xb3, 0xd7, 0xec, 0xcc, },
+}};
+
+static const struct hash_testvec blakes2s_256_tv_template[] = {{
+ .plaintext = blake2_ordered_sequence,
+ .psize = 15,
+ .digest = (u8[]){ 0xd9, 0x7c, 0x82, 0x8d, 0x81, 0x82, 0xa7, 0x21,
+ 0x80, 0xa0, 0x6a, 0x78, 0x26, 0x83, 0x30, 0x67,
+ 0x3f, 0x7c, 0x4e, 0x06, 0x35, 0x94, 0x7c, 0x04,
+ 0xc0, 0x23, 0x23, 0xfd, 0x45, 0xc0, 0xa5, 0x2d, },
+}, {
+ .ksize = 32,
+ .key = blake2_ordered_sequence,
+ .digest = (u8[]){ 0x48, 0xa8, 0x99, 0x7d, 0xa4, 0x07, 0x87, 0x6b,
+ 0x3d, 0x79, 0xc0, 0xd9, 0x23, 0x25, 0xad, 0x3b,
+ 0x89, 0xcb, 0xb7, 0x54, 0xd8, 0x6a, 0xb7, 0x1a,
+ 0xee, 0x04, 0x7a, 0xd3, 0x45, 0xfd, 0x2c, 0x49, },
+}, {
+ .ksize = 1,
+ .key = "B",
+ .plaintext = blake2_ordered_sequence,
+ .psize = 1,
+ .digest = (u8[]){ 0x22, 0x27, 0xae, 0xaa, 0x6e, 0x81, 0x56, 0x03,
+ 0xa7, 0xe3, 0xa1, 0x18, 0xa5, 0x9a, 0x2c, 0x18,
+ 0xf4, 0x63, 0xbc, 0x16, 0x70, 0xf1, 0xe7, 0x4b,
+ 0x00, 0x6d, 0x66, 0x16, 0xae, 0x9e, 0x74, 0x4e, },
+}, {
+ .ksize = 16,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 7,
+ .digest = (u8[]){ 0x58, 0x5d, 0xa8, 0x60, 0x1c, 0xa4, 0xd8, 0x03,
+ 0x86, 0x86, 0x84, 0x64, 0xd7, 0xa0, 0x8e, 0x15,
+ 0x2f, 0x05, 0xa2, 0x1b, 0xbc, 0xef, 0x7a, 0x34,
+ 0xb3, 0xc5, 0xbc, 0x4b, 0xf0, 0x32, 0xeb, 0x12, },
+}, {
+ .ksize = 32,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 64,
+ .digest = (u8[]){ 0x89, 0x75, 0xb0, 0x57, 0x7f, 0xd3, 0x55, 0x66,
+ 0xd7, 0x50, 0xb3, 0x62, 0xb0, 0x89, 0x7a, 0x26,
+ 0xc3, 0x99, 0x13, 0x6d, 0xf0, 0x7b, 0xab, 0xab,
+ 0xbd, 0xe6, 0x20, 0x3f, 0xf2, 0x95, 0x4e, 0xd4, },
+}, {
+ .ksize = 1,
+ .key = "B",
+ .plaintext = blake2_ordered_sequence,
+ .psize = 247,
+ .digest = (u8[]){ 0x2e, 0x74, 0x1c, 0x1d, 0x03, 0xf4, 0x9d, 0x84,
+ 0x6f, 0xfc, 0x86, 0x32, 0x92, 0x49, 0x7e, 0x66,
+ 0xd7, 0xc3, 0x10, 0x88, 0xfe, 0x28, 0xb3, 0xe0,
+ 0xbf, 0x50, 0x75, 0xad, 0x8e, 0xa4, 0xe6, 0xb2, },
+}, {
+ .ksize = 16,
+ .key = blake2_ordered_sequence,
+ .plaintext = blake2_ordered_sequence,
+ .psize = 256,
+ .digest = (u8[]){ 0xb9, 0xd2, 0x81, 0x0e, 0x3a, 0xb1, 0x62, 0x9b,
+ 0xad, 0x44, 0x05, 0xf4, 0x92, 0x2e, 0x99, 0xc1,
+ 0x4a, 0x47, 0xbb, 0x5b, 0x6f, 0xb2, 0x96, 0xed,
+ 0xd5, 0x06, 0xb5, 0x3a, 0x7c, 0x7a, 0x65, 0x1d, },
+}};
+
#endif /* _CRYPTO_TESTMGR_H */

Some files were not shown because too many files have changed in this diff Show More