xref: /linux-6.15/drivers/crypto/caam/error.c (revision 867e1ee3)
18e8ec596SKim Phillips /*
28e8ec596SKim Phillips  * CAAM Error Reporting
38e8ec596SKim Phillips  *
48e8ec596SKim Phillips  * Copyright 2009-2011 Freescale Semiconductor, Inc.
58e8ec596SKim Phillips  */
68e8ec596SKim Phillips 
78e8ec596SKim Phillips #include "compat.h"
88e8ec596SKim Phillips #include "regs.h"
98e8ec596SKim Phillips #include "intern.h"
108e8ec596SKim Phillips #include "desc.h"
118e8ec596SKim Phillips #include "jr.h"
128e8ec596SKim Phillips #include "error.h"
138e8ec596SKim Phillips 
1496aef9a8SKim Phillips static const struct {
158e8ec596SKim Phillips 	u8 value;
168e8ec596SKim Phillips 	char *error_text;
178e8ec596SKim Phillips } desc_error_list[] = {
18281922a1SKim Phillips 	{ 0x00, "No error." },
198e8ec596SKim Phillips 	{ 0x01, "SGT Length Error. The descriptor is trying to read "
208e8ec596SKim Phillips 		"more data than is contained in the SGT table." },
21281922a1SKim Phillips 	{ 0x02, "SGT Null Entry Error." },
228e8ec596SKim Phillips 	{ 0x03, "Job Ring Control Error. There is a bad value in the "
238e8ec596SKim Phillips 		"Job Ring Control register." },
248e8ec596SKim Phillips 	{ 0x04, "Invalid Descriptor Command. The Descriptor Command "
258e8ec596SKim Phillips 		"field is invalid." },
268e8ec596SKim Phillips 	{ 0x05, "Reserved." },
278e8ec596SKim Phillips 	{ 0x06, "Invalid KEY Command" },
288e8ec596SKim Phillips 	{ 0x07, "Invalid LOAD Command" },
298e8ec596SKim Phillips 	{ 0x08, "Invalid STORE Command" },
308e8ec596SKim Phillips 	{ 0x09, "Invalid OPERATION Command" },
318e8ec596SKim Phillips 	{ 0x0A, "Invalid FIFO LOAD Command" },
328e8ec596SKim Phillips 	{ 0x0B, "Invalid FIFO STORE Command" },
33281922a1SKim Phillips 	{ 0x0C, "Invalid MOVE/MOVE_LEN Command" },
348e8ec596SKim Phillips 	{ 0x0D, "Invalid JUMP Command. A nonlocal JUMP Command is "
358e8ec596SKim Phillips 		"invalid because the target is not a Job Header "
368e8ec596SKim Phillips 		"Command, or the jump is from a Trusted Descriptor to "
378e8ec596SKim Phillips 		"a Job Descriptor, or because the target Descriptor "
388e8ec596SKim Phillips 		"contains a Shared Descriptor." },
398e8ec596SKim Phillips 	{ 0x0E, "Invalid MATH Command" },
408e8ec596SKim Phillips 	{ 0x0F, "Invalid SIGNATURE Command" },
418e8ec596SKim Phillips 	{ 0x10, "Invalid Sequence Command. A SEQ IN PTR OR SEQ OUT PTR "
428e8ec596SKim Phillips 		"Command is invalid or a SEQ KEY, SEQ LOAD, SEQ FIFO "
438e8ec596SKim Phillips 		"LOAD, or SEQ FIFO STORE decremented the input or "
448e8ec596SKim Phillips 		"output sequence length below 0. This error may result "
458e8ec596SKim Phillips 		"if a built-in PROTOCOL Command has encountered a "
468e8ec596SKim Phillips 		"malformed PDU." },
478e8ec596SKim Phillips 	{ 0x11, "Skip data type invalid. The type must be 0xE or 0xF."},
488e8ec596SKim Phillips 	{ 0x12, "Shared Descriptor Header Error" },
498e8ec596SKim Phillips 	{ 0x13, "Header Error. Invalid length or parity, or certain "
508e8ec596SKim Phillips 		"other problems." },
518e8ec596SKim Phillips 	{ 0x14, "Burster Error. Burster has gotten to an illegal "
528e8ec596SKim Phillips 		"state" },
538e8ec596SKim Phillips 	{ 0x15, "Context Register Length Error. The descriptor is "
548e8ec596SKim Phillips 		"trying to read or write past the end of the Context "
558e8ec596SKim Phillips 		"Register. A SEQ LOAD or SEQ STORE with the VLF bit "
568e8ec596SKim Phillips 		"set was executed with too large a length in the "
578e8ec596SKim Phillips 		"variable length register (VSOL for SEQ STORE or VSIL "
588e8ec596SKim Phillips 		"for SEQ LOAD)." },
598e8ec596SKim Phillips 	{ 0x16, "DMA Error" },
608e8ec596SKim Phillips 	{ 0x17, "Reserved." },
618e8ec596SKim Phillips 	{ 0x1A, "Job failed due to JR reset" },
628e8ec596SKim Phillips 	{ 0x1B, "Job failed due to Fail Mode" },
638e8ec596SKim Phillips 	{ 0x1C, "DECO Watchdog timer timeout error" },
648e8ec596SKim Phillips 	{ 0x1D, "DECO tried to copy a key from another DECO but the "
658e8ec596SKim Phillips 		"other DECO's Key Registers were locked" },
668e8ec596SKim Phillips 	{ 0x1E, "DECO attempted to copy data from a DECO that had an "
678e8ec596SKim Phillips 		"unmasked Descriptor error" },
688e8ec596SKim Phillips 	{ 0x1F, "LIODN error. DECO was trying to share from itself or "
698e8ec596SKim Phillips 		"from another DECO but the two Non-SEQ LIODN values "
708e8ec596SKim Phillips 		"didn't match or the 'shared from' DECO's Descriptor "
718e8ec596SKim Phillips 		"required that the SEQ LIODNs be the same and they "
728e8ec596SKim Phillips 		"aren't." },
738e8ec596SKim Phillips 	{ 0x20, "DECO has completed a reset initiated via the DRR "
748e8ec596SKim Phillips 		"register" },
758e8ec596SKim Phillips 	{ 0x21, "Nonce error. When using EKT (CCM) key encryption "
768e8ec596SKim Phillips 		"option in the FIFO STORE Command, the Nonce counter "
778e8ec596SKim Phillips 		"reached its maximum value and this encryption mode "
788e8ec596SKim Phillips 		"can no longer be used." },
798e8ec596SKim Phillips 	{ 0x22, "Meta data is too large (> 511 bytes) for TLS decap "
808e8ec596SKim Phillips 		"(input frame; block ciphers) and IPsec decap (output "
818e8ec596SKim Phillips 		"frame, when doing the next header byte update) and "
828e8ec596SKim Phillips 		"DCRC (output frame)." },
83281922a1SKim Phillips 	{ 0x23, "Read Input Frame error" },
84281922a1SKim Phillips 	{ 0x24, "JDKEK, TDKEK or TDSK not loaded error" },
858e8ec596SKim Phillips 	{ 0x80, "DNR (do not run) error" },
868e8ec596SKim Phillips 	{ 0x81, "undefined protocol command" },
878e8ec596SKim Phillips 	{ 0x82, "invalid setting in PDB" },
888e8ec596SKim Phillips 	{ 0x83, "Anti-replay LATE error" },
898e8ec596SKim Phillips 	{ 0x84, "Anti-replay REPLAY error" },
908e8ec596SKim Phillips 	{ 0x85, "Sequence number overflow" },
918e8ec596SKim Phillips 	{ 0x86, "Sigver invalid signature" },
928e8ec596SKim Phillips 	{ 0x87, "DSA Sign Illegal test descriptor" },
938e8ec596SKim Phillips 	{ 0x88, "Protocol Format Error - A protocol has seen an error "
948e8ec596SKim Phillips 		"in the format of data received. When running RSA, "
958e8ec596SKim Phillips 		"this means that formatting with random padding was "
968e8ec596SKim Phillips 		"used, and did not follow the form: 0x00, 0x02, 8-to-N "
978e8ec596SKim Phillips 		"bytes of non-zero pad, 0x00, F data." },
988e8ec596SKim Phillips 	{ 0x89, "Protocol Size Error - A protocol has seen an error in "
998e8ec596SKim Phillips 		"size. When running RSA, pdb size N < (size of F) when "
1008e8ec596SKim Phillips 		"no formatting is used; or pdb size N < (F + 11) when "
1018e8ec596SKim Phillips 		"formatting is used." },
1028e8ec596SKim Phillips 	{ 0xC1, "Blob Command error: Undefined mode" },
1038e8ec596SKim Phillips 	{ 0xC2, "Blob Command error: Secure Memory Blob mode error" },
1048e8ec596SKim Phillips 	{ 0xC4, "Blob Command error: Black Blob key or input size "
1058e8ec596SKim Phillips 		"error" },
1068e8ec596SKim Phillips 	{ 0xC5, "Blob Command error: Invalid key destination" },
1078e8ec596SKim Phillips 	{ 0xC8, "Blob Command error: Trusted/Secure mode error" },
1088e8ec596SKim Phillips 	{ 0xF0, "IPsec TTL or hop limit field either came in as 0, "
1098e8ec596SKim Phillips 		"or was decremented to 0" },
1108e8ec596SKim Phillips 	{ 0xF1, "3GPP HFN matches or exceeds the Threshold" },
1118e8ec596SKim Phillips };
1129724d7adSMarek Vasut 
1139724d7adSMarek Vasut static const char * const cha_id_list[] = {
1149724d7adSMarek Vasut 	"",
1159724d7adSMarek Vasut 	"AES",
1169724d7adSMarek Vasut 	"DES",
1179724d7adSMarek Vasut 	"ARC4",
1189724d7adSMarek Vasut 	"MDHA",
1199724d7adSMarek Vasut 	"RNG",
1209724d7adSMarek Vasut 	"SNOW f8",
1219724d7adSMarek Vasut 	"Kasumi f8/9",
1229724d7adSMarek Vasut 	"PKHA",
1239724d7adSMarek Vasut 	"CRCA",
1249724d7adSMarek Vasut 	"SNOW f9",
1259724d7adSMarek Vasut 	"ZUCE",
1269724d7adSMarek Vasut 	"ZUCA",
1279724d7adSMarek Vasut };
1289724d7adSMarek Vasut 
1299724d7adSMarek Vasut static const char * const err_id_list[] = {
1309724d7adSMarek Vasut 	"No error.",
1319724d7adSMarek Vasut 	"Mode error.",
1329724d7adSMarek Vasut 	"Data size error.",
1339724d7adSMarek Vasut 	"Key size error.",
1349724d7adSMarek Vasut 	"PKHA A memory size error.",
1359724d7adSMarek Vasut 	"PKHA B memory size error.",
1369724d7adSMarek Vasut 	"Data arrived out of sequence error.",
1379724d7adSMarek Vasut 	"PKHA divide-by-zero error.",
1389724d7adSMarek Vasut 	"PKHA modulus even error.",
1399724d7adSMarek Vasut 	"DES key parity error.",
1409724d7adSMarek Vasut 	"ICV check failed.",
1419724d7adSMarek Vasut 	"Hardware error.",
1429724d7adSMarek Vasut 	"Unsupported CCM AAD size.",
1439724d7adSMarek Vasut 	"Class 1 CHA is not reset",
1449724d7adSMarek Vasut 	"Invalid CHA combination was selected",
1459724d7adSMarek Vasut 	"Invalid CHA selected.",
1469724d7adSMarek Vasut };
1479724d7adSMarek Vasut 
1489724d7adSMarek Vasut static const char * const rng_err_id_list[] = {
1499724d7adSMarek Vasut 	"",
1509724d7adSMarek Vasut 	"",
1519724d7adSMarek Vasut 	"",
1529724d7adSMarek Vasut 	"Instantiate",
1539724d7adSMarek Vasut 	"Not instantiated",
1549724d7adSMarek Vasut 	"Test instantiate",
1559724d7adSMarek Vasut 	"Prediction resistance",
1569724d7adSMarek Vasut 	"Prediction resistance and test request",
1579724d7adSMarek Vasut 	"Uninstantiate",
1589724d7adSMarek Vasut 	"Secure key generation",
1599724d7adSMarek Vasut };
1609724d7adSMarek Vasut 
1619724d7adSMarek Vasut #define SPRINTFCAT(str, format, param, max_alloc)		\
1629724d7adSMarek Vasut {								\
1639724d7adSMarek Vasut 	char *tmp;						\
1649724d7adSMarek Vasut 								\
1659724d7adSMarek Vasut 	tmp = kmalloc(sizeof(format) + max_alloc, GFP_ATOMIC);	\
1669724d7adSMarek Vasut 	sprintf(tmp, format, param);				\
1679724d7adSMarek Vasut 	strcat(str, tmp);					\
1689724d7adSMarek Vasut 	kfree(tmp);						\
1699724d7adSMarek Vasut }
1709724d7adSMarek Vasut 
1719724d7adSMarek Vasut static void report_jump_idx(u32 status, char *outstr)
1729724d7adSMarek Vasut {
1739724d7adSMarek Vasut 	u8 idx = (status & JRSTA_DECOERR_INDEX_MASK) >>
1749724d7adSMarek Vasut 		  JRSTA_DECOERR_INDEX_SHIFT;
1759724d7adSMarek Vasut 
1769724d7adSMarek Vasut 	if (status & JRSTA_DECOERR_JUMP)
1779724d7adSMarek Vasut 		strcat(outstr, "jump tgt desc idx ");
1789724d7adSMarek Vasut 	else
1799724d7adSMarek Vasut 		strcat(outstr, "desc idx ");
1809724d7adSMarek Vasut 
1819724d7adSMarek Vasut 	SPRINTFCAT(outstr, "%d: ", idx, sizeof("255"));
1829724d7adSMarek Vasut }
1839724d7adSMarek Vasut 
1849724d7adSMarek Vasut static void report_ccb_status(u32 status, char *outstr)
1859724d7adSMarek Vasut {
1869724d7adSMarek Vasut 	u8 cha_id = (status & JRSTA_CCBERR_CHAID_MASK) >>
1879724d7adSMarek Vasut 		    JRSTA_CCBERR_CHAID_SHIFT;
1889724d7adSMarek Vasut 	u8 err_id = status & JRSTA_CCBERR_ERRID_MASK;
1899724d7adSMarek Vasut 
1909724d7adSMarek Vasut 	report_jump_idx(status, outstr);
1919724d7adSMarek Vasut 
1929724d7adSMarek Vasut 	if (cha_id < ARRAY_SIZE(cha_id_list)) {
1939724d7adSMarek Vasut 		SPRINTFCAT(outstr, "%s: ", cha_id_list[cha_id],
1949724d7adSMarek Vasut 			   strlen(cha_id_list[cha_id]));
1959724d7adSMarek Vasut 	} else {
1969724d7adSMarek Vasut 		SPRINTFCAT(outstr, "unidentified cha_id value 0x%02x: ",
1979724d7adSMarek Vasut 			   cha_id, sizeof("ff"));
1989724d7adSMarek Vasut 	}
1999724d7adSMarek Vasut 
2009724d7adSMarek Vasut 	if ((cha_id << JRSTA_CCBERR_CHAID_SHIFT) == JRSTA_CCBERR_CHAID_RNG &&
2019724d7adSMarek Vasut 	    err_id < ARRAY_SIZE(rng_err_id_list) &&
2029724d7adSMarek Vasut 	    strlen(rng_err_id_list[err_id])) {
2039724d7adSMarek Vasut 		/* RNG-only error */
2049724d7adSMarek Vasut 		SPRINTFCAT(outstr, "%s", rng_err_id_list[err_id],
2059724d7adSMarek Vasut 			   strlen(rng_err_id_list[err_id]));
2069724d7adSMarek Vasut 	} else if (err_id < ARRAY_SIZE(err_id_list)) {
2079724d7adSMarek Vasut 		SPRINTFCAT(outstr, "%s", err_id_list[err_id],
2089724d7adSMarek Vasut 			   strlen(err_id_list[err_id]));
2099724d7adSMarek Vasut 	} else {
2109724d7adSMarek Vasut 		SPRINTFCAT(outstr, "unidentified err_id value 0x%02x",
2119724d7adSMarek Vasut 			   err_id, sizeof("ff"));
2129724d7adSMarek Vasut 	}
2139724d7adSMarek Vasut }
2149724d7adSMarek Vasut 
2159724d7adSMarek Vasut static void report_jump_status(u32 status, char *outstr)
2169724d7adSMarek Vasut {
2179724d7adSMarek Vasut 	SPRINTFCAT(outstr, "%s() not implemented", __func__, sizeof(__func__));
2189724d7adSMarek Vasut }
2199724d7adSMarek Vasut 
2209724d7adSMarek Vasut static void report_deco_status(u32 status, char *outstr)
2219724d7adSMarek Vasut {
2228e8ec596SKim Phillips 	u8 desc_error = status & JRSTA_DECOERR_ERROR_MASK;
2238e8ec596SKim Phillips 	int i;
2248e8ec596SKim Phillips 
2258e8ec596SKim Phillips 	report_jump_idx(status, outstr);
2268e8ec596SKim Phillips 
2276d00376aSDan Carpenter 	for (i = 0; i < ARRAY_SIZE(desc_error_list); i++)
2288e8ec596SKim Phillips 		if (desc_error_list[i].value == desc_error)
2298e8ec596SKim Phillips 			break;
2308e8ec596SKim Phillips 
2316d00376aSDan Carpenter 	if (i != ARRAY_SIZE(desc_error_list) && desc_error_list[i].error_text) {
2328e8ec596SKim Phillips 		SPRINTFCAT(outstr, "%s", desc_error_list[i].error_text,
2338e8ec596SKim Phillips 			   strlen(desc_error_list[i].error_text));
2348e8ec596SKim Phillips 	} else {
2358e8ec596SKim Phillips 		SPRINTFCAT(outstr, "unidentified error value 0x%02x",
2368e8ec596SKim Phillips 			   desc_error, sizeof("ff"));
2378e8ec596SKim Phillips 	}
2388e8ec596SKim Phillips }
2398e8ec596SKim Phillips 
2408e8ec596SKim Phillips static void report_jr_status(u32 status, char *outstr)
2418e8ec596SKim Phillips {
2428e8ec596SKim Phillips 	SPRINTFCAT(outstr, "%s() not implemented", __func__, sizeof(__func__));
2438e8ec596SKim Phillips }
2448e8ec596SKim Phillips 
2458e8ec596SKim Phillips static void report_cond_code_status(u32 status, char *outstr)
2468e8ec596SKim Phillips {
2478e8ec596SKim Phillips 	SPRINTFCAT(outstr, "%s() not implemented", __func__, sizeof(__func__));
2488e8ec596SKim Phillips }
2498e8ec596SKim Phillips 
250fa9659cdSMarek Vasut void caam_jr_strstatus(struct device *jrdev, u32 status)
2518e8ec596SKim Phillips {
252fa9659cdSMarek Vasut 	char outstr[CAAM_ERROR_STR_MAX];
25396aef9a8SKim Phillips 	static const struct stat_src {
2548e8ec596SKim Phillips 		void (*report_ssed)(u32 status, char *outstr);
2558e8ec596SKim Phillips 		char *error;
2568e8ec596SKim Phillips 	} status_src[] = {
2578e8ec596SKim Phillips 		{ NULL, "No error" },
2588e8ec596SKim Phillips 		{ NULL, NULL },
2598e8ec596SKim Phillips 		{ report_ccb_status, "CCB" },
2608e8ec596SKim Phillips 		{ report_jump_status, "Jump" },
2618e8ec596SKim Phillips 		{ report_deco_status, "DECO" },
2628e8ec596SKim Phillips 		{ NULL, NULL },
2638e8ec596SKim Phillips 		{ report_jr_status, "Job Ring" },
2648e8ec596SKim Phillips 		{ report_cond_code_status, "Condition Code" },
2658e8ec596SKim Phillips 	};
2668e8ec596SKim Phillips 	u32 ssrc = status >> JRSTA_SSRC_SHIFT;
2678e8ec596SKim Phillips 
268*867e1ee3SMarek Vasut 	/*
269*867e1ee3SMarek Vasut 	 * If there is no further error handling function, just
270*867e1ee3SMarek Vasut 	 * print the error code, error string and exit.
271*867e1ee3SMarek Vasut 	 */
272*867e1ee3SMarek Vasut 	if (!status_src[ssrc].report_ssed) {
273*867e1ee3SMarek Vasut 		dev_err(jrdev, "%08x: %s: \n", status, status_src[ssrc].error);
274*867e1ee3SMarek Vasut 		return;
275*867e1ee3SMarek Vasut 	}
276*867e1ee3SMarek Vasut 
2778e8ec596SKim Phillips 	sprintf(outstr, "%s: ", status_src[ssrc].error);
2788e8ec596SKim Phillips 
2798e8ec596SKim Phillips 	status_src[ssrc].report_ssed(status, outstr);
2808e8ec596SKim Phillips 
281fa9659cdSMarek Vasut 	dev_err(jrdev, "%08x: %s\n", status, outstr);
2828e8ec596SKim Phillips }
2838e8ec596SKim Phillips EXPORT_SYMBOL(caam_jr_strstatus);
284