~funderscore blog cgit wiki get in touch
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plat/gxb/crypto')
-rw-r--r--plat/gxb/crypto/bignum.c1355
-rw-r--r--plat/gxb/crypto/ndma_utils.c183
-rw-r--r--plat/gxb/crypto/rsa.c240
-rw-r--r--plat/gxb/crypto/secureboot.c749
4 files changed, 2527 insertions, 0 deletions
diff --git a/plat/gxb/crypto/bignum.c b/plat/gxb/crypto/bignum.c
new file mode 100644
index 0000000..ac0c811
--- /dev/null
+++ b/plat/gxb/crypto/bignum.c
@@ -0,0 +1,1355 @@
+/*
+ * Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This MPI implementation is based on:
+ *
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ * http://www.stillhq.com/extracted/gnupg-api/mpi/
+ * http://math.libtomcrypt.com/files/tommath.pdf
+ */
+
+#include "common.h"
+#include <string.h>
+#include <rsa_config.h>
+#include <stdio.h>
+
+
+#if defined(POLARSSL_BIGNUM_C)
+
+#include "bignum.h"
+#include "bn_mul.h"
+
+#define ciL (sizeof(t_uint)) /* chars in limb */
+#define biL (ciL << 3) /* bits in limb */
+#define biH (ciL << 2) /* half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ */
+#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
+#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+
+
+#define CONFIG_MALLOC_MAX (128 * 1024)
+
+//char malloc_buffer[CONFIG_MALLOC_MAX];
+//static unsigned char * malloc_buffer = (unsigned char *)(0x10400000);
+static int malloc_addr = 0;
+
+void *mymalloc(int size)
+{
+ void *p;
+
+ if (malloc_addr + size > CONFIG_MALLOC_MAX)
+ p = NULL;
+ else
+ //p = (char *)&malloc_buffer[0] + malloc_addr;
+ p = (char *)(unsigned long)(0x1700000+ malloc_addr);
+
+ if (p)
+ malloc_addr += size;
+ //ss_printf("malloc size %d/%d addr %p\n", size, malloc_addr, p);
+
+ //printf("aml log : malloc_buffer=%p malloc_addr=0x%x p=%p size=%d\n",
+ // malloc_buffer,malloc_addr,p,size);
+
+ return p;
+}
+
+void myfree(void *ptr)
+{
+}
+
+void mymallocreset()
+{
+ malloc_addr = 0;
+}
+
+
+/*
+ * Initialize one MPI
+ */
+void mpi_init( mpi *X )
+{
+ if ( X == NULL )
+ return;
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Unallocate one MPI
+ */
+void mpi_free( mpi *X )
+{
+ if ( X == NULL )
+ return;
+
+ if ( X->p != NULL )
+ {
+ memset( X->p, 0, X->n * ciL );
+ myfree( X->p );
+ }
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mpi_grow( mpi *X, size_t nblimbs )
+{
+ t_uint *p;
+
+ if ( nblimbs > POLARSSL_MPI_MAX_LIMBS )
+ return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+
+ if ( X->n < nblimbs )
+ {
+
+ if ( ( p = (t_uint *) mymalloc( nblimbs * ciL ) ) == NULL )
+ return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+ memset( p, 0, nblimbs * ciL );
+
+ if ( X->p != NULL )
+ {
+ memcpy( p, X->p, X->n * ciL );
+ memset( X->p, 0, X->n * ciL );
+ myfree( X->p );
+ }
+
+ X->n = nblimbs;
+ X->p = p;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mpi_copy( mpi *X, const mpi *Y )
+{
+ int ret;
+ size_t i;
+
+ if ( X == Y )
+ return( 0 );
+
+ for ( i = Y->n - 1; i > 0; i-- )
+ if ( Y->p[i] != 0 )
+ break;
+ i++;
+
+ X->s = Y->s;
+
+ MPI_CHK( mpi_grow( X, i ) );
+
+ memset( X->p, 0, X->n * ciL );
+ memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y )
+{
+ mpi T;
+
+ memcpy( &T, X, sizeof( mpi ) );
+ memcpy( X, Y, sizeof( mpi ) );
+ memcpy( Y, &T, sizeof( mpi ) );
+}
+
+/*
+ * Set value from integer
+ */
+int mpi_lset( mpi *X, t_sint z )
+{
+ int ret;
+
+ MPI_CHK( mpi_grow( X, 1 ) );
+ memset( X->p, 0, X->n * ciL );
+
+ X->p[0] = ( z < 0 ) ? -z : z;
+ X->s = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Get a specific bit
+ */
+int mpi_get_bit( const mpi *X, size_t pos )
+{
+ if ( X->n * biL <= pos )
+ return( 0 );
+
+ return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
+}
+
+/*
+ * Set a bit to a specific value of 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
+{
+ int ret = 0;
+ size_t off = pos / biL;
+ size_t idx = pos % biL;
+
+ if ( val != 0 && val != 1 )
+ return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
+
+ if ( X->n * biL <= pos )
+ {
+ if ( val == 0 )
+ return ( 0 );
+
+ MPI_CHK( mpi_grow( X, off + 1 ) );
+ }
+
+ X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Return the number of least significant bits
+ */
+size_t mpi_lsb( const mpi *X )
+{
+ size_t i, j, count = 0;
+
+ for ( i = 0; i < X->n; i++ )
+ for ( j = 0; j < biL; j++, count++ )
+ if ( ( ( X->p[i] >> j ) & 1 ) != 0 )
+ return( count );
+
+ return( 0 );
+}
+
+/*
+ * Return the number of most significant bits
+ */
+size_t mpi_msb( const mpi *X )
+{
+ size_t i, j;
+
+ for ( i = X->n - 1; i > 0; i-- )
+ if ( X->p[i] != 0 )
+ break;
+
+ for ( j = biL; j > 0; j-- )
+ if ( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
+ break;
+
+ return( ( i * biL ) + j );
+}
+
+/*
+ * Return the total size in bytes
+ */
+size_t mpi_size( const mpi *X )
+{
+ return( ( mpi_msb( X ) + 7 ) >> 3 );
+}
+
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
+{
+ int ret;
+ size_t i, j, n;
+
+ for ( n = 0; n < buflen; n++ )
+ if ( buf[n] != 0 )
+ break;
+ MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
+
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+
+ for ( i = buflen, j = 0; i > n; i--, j++ )
+ X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
+{
+ size_t i, j, n;
+
+ n = mpi_size( X );
+
+ if ( buflen < n )
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+ memset( buf, 0, buflen );
+
+ for ( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+ buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+ return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mpi_shift_l( mpi *X, size_t count )
+{
+ int ret;
+ size_t i, v0, t1;
+ t_uint r0 = 0, r1;
+
+ v0 = count / (biL );
+ t1 = count & (biL - 1);
+
+ i = mpi_msb( X ) + count;
+
+ if ( X->n * biL < i )
+ MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+ ret = 0;
+
+ /*
+ * shift by count / limb_size
+ */
+ if ( v0 > 0 )
+ {
+ for ( i = X->n; i > v0; i-- )
+ X->p[i - 1] = X->p[i - v0 - 1];
+
+ for ( ; i > 0; i-- )
+ X->p[i - 1] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if ( t1 > 0 )
+ {
+ for ( i = v0; i < X->n; i++ )
+ {
+ r1 = X->p[i] >> (biL - t1);
+ X->p[i] <<= t1;
+ X->p[i] |= r0;
+ r0 = r1;
+ }
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mpi_shift_r( mpi *X, size_t count )
+{
+ size_t i, v0, v1;
+ t_uint r0 = 0, r1;
+
+ v0 = count / biL;
+ v1 = count & (biL - 1);
+
+ if ( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
+ return mpi_lset( X, 0 );
+
+ /*
+ * shift by count / limb_size
+ */
+ if ( v0 > 0 )
+ {
+ for ( i = 0; i < X->n - v0; i++ )
+ X->p[i] = X->p[i + v0];
+
+ for ( ; i < X->n; i++ )
+ X->p[i] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if ( v1 > 0 )
+ {
+ for ( i = X->n; i > 0; i-- )
+ {
+ r1 = X->p[i - 1] << (biL - v1);
+ X->p[i - 1] >>= v1;
+ X->p[i - 1] |= r0;
+ r0 = r1;
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y )
+{
+ size_t i, j;
+
+ for ( i = X->n; i > 0; i-- )
+ if ( X->p[i - 1] != 0 )
+ break;
+
+ for ( j = Y->n; j > 0; j-- )
+ if ( Y->p[j - 1] != 0 )
+ break;
+
+ if ( i == 0 && j == 0 )
+ return( 0 );
+
+ if ( i > j ) return( 1 ) ;
+ if ( j > i ) return( -1 ) ;
+
+ for ( ; i > 0; i-- )
+ {
+ if ( X->p[i - 1] > Y->p[i - 1] ) return( 1 ) ;
+ if ( X->p[i - 1] < Y->p[i - 1] ) return( -1 ) ;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y )
+{
+ size_t i, j;
+
+ for ( i = X->n; i > 0; i-- )
+ if ( X->p[i - 1] != 0 )
+ break;
+
+ for ( j = Y->n; j > 0; j-- )
+ if ( Y->p[j - 1] != 0 )
+ break;
+
+ if ( i == 0 && j == 0 )
+ return( 0 );
+
+ if ( i > j ) return( X->s ) ;
+ if ( j > i ) return( -Y->s ) ;
+
+ if ( X->s > 0 && Y->s < 0 ) return( 1 ) ;
+ if ( Y->s > 0 && X->s < 0 ) return( -1 ) ;
+
+ for ( ; i > 0; i-- )
+ {
+ if ( X->p[i - 1] > Y->p[i - 1] ) return( X->s ) ;
+ if ( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ) ;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_int( const mpi *X, t_sint z )
+{
+ mpi Y;
+ t_uint p[1];
+
+ *p = ( z < 0 ) ? -z : z;
+ Y.s = ( z < 0 ) ? -1 : 1;
+ Y.n = 1;
+ Y.p = p;
+
+ return( mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B| (HAC 14.7)
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, j;
+ t_uint *o, *p, c;
+
+ if ( X == B )
+ {
+ const mpi *T = A; A = X; B = T;
+ }
+
+ if ( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned additions.
+ */
+ X->s = 1;
+
+ for ( j = B->n; j > 0; j-- )
+ if ( B->p[j - 1] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, j ) );
+
+ o = B->p; p = X->p; c = 0;
+
+ for ( i = 0; i < j; i++, o++, p++ )
+ {
+ *p += c; c = ( *p < c );
+ *p += *o; c += ( *p < *o );
+ }
+
+ while ( c != 0 )
+ {
+ if ( i >= X->n )
+ {
+ MPI_CHK( mpi_grow( X, i + 1 ) );
+ p = X->p + i;
+ }
+
+ *p += c; c = ( *p < c ); i++; p++;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Helper for mpi substraction
+ */
+static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
+{
+ size_t i;
+ t_uint c, z;
+
+ for ( i = c = 0; i < n; i++, s++, d++ )
+ {
+ z = ( *d < c ); *d -= c;
+ c = ( *d < *s ) + z; *d -= *s;
+ }
+
+ while ( c != 0 )
+ {
+ z = ( *d < c ); *d -= c;
+ c = z; i++; d++;
+ }
+}
+
+/*
+ * Unsigned substraction: X = |A| - |B| (HAC 14.9)
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
+{
+ mpi TB;
+ int ret;
+ size_t n;
+
+ if ( mpi_cmp_abs( A, B ) < 0 )
+ return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
+
+ mpi_init( &TB );
+
+ if ( X == B )
+ {
+ MPI_CHK( mpi_copy( &TB, B ) );
+ B = &TB;
+ }
+
+ if ( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned substractions.
+ */
+ X->s = 1;
+
+ ret = 0;
+
+ for ( n = B->n; n > 0; n-- )
+ if ( B->p[n - 1] != 0 )
+ break;
+
+ mpi_sub_hlp( n, B->p, X->p );
+
+cleanup:
+
+ mpi_free( &TB );
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret, s = A->s;
+
+ if ( A->s * B->s < 0 )
+ {
+ if ( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed substraction: X = A - B
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret, s = A->s;
+
+ if ( A->s * B->s > 0 )
+ {
+ if ( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed substraction: X = A - b
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mpi multiplication
+ */
+static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
+{
+ t_uint c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+ for ( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_HUIT
+ MULADDC_STOP
+ }
+
+ for ( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#else
+ for ( ; i >= 16; i -= 16 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for ( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for ( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#endif
+
+ t++;
+
+ do {
+ *d += c; c = ( *d < c ); d++;
+ }
+ while ( c != 0 ) ;
+}
+
+/*
+ * Baseline multiplication: X = A * B (HAC 14.12)
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, j;
+ mpi TA, TB;
+
+ mpi_init( &TA ); mpi_init( &TB );
+
+ if ( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ) ; A = &TA; }
+ if ( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ) ; B = &TB; }
+
+ for ( i = A->n; i > 0; i-- )
+ if ( A->p[i - 1] != 0 )
+ break;
+
+ for ( j = B->n; j > 0; j-- )
+ if ( B->p[j - 1] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, i + j ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for ( i++; j > 0; j-- )
+ mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
+
+ X->s = A->s * B->s;
+
+cleanup:
+
+ mpi_free( &TB ); mpi_free( &TA );
+
+ return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ _B.s = 1;
+ _B.n = 1;
+ _B.p = p;
+ p[0] = b;
+
+ return( mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Division by mpi: A = Q * B + R (HAC 14.20)
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, n, t, k;
+ mpi X, Y, Z, T1, T2;
+
+ if ( mpi_cmp_int( B, 0 ) == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
+ mpi_init( &T1 ); mpi_init( &T2 );
+
+ if ( mpi_cmp_abs( A, B ) < 0 )
+ {
+ if ( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ) ;
+ if ( R != NULL ) MPI_CHK( mpi_copy( R, A ) ) ;
+ return( 0 );
+ }
+
+ MPI_CHK( mpi_copy( &X, A ) );
+ MPI_CHK( mpi_copy( &Y, B ) );
+ X.s = Y.s = 1;
+
+ MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
+ MPI_CHK( mpi_lset( &Z, 0 ) );
+ MPI_CHK( mpi_grow( &T1, 2 ) );
+ MPI_CHK( mpi_grow( &T2, 3 ) );
+
+ k = mpi_msb( &Y ) % biL;
+ if ( k < biL - 1 )
+ {
+ k = biL - 1 - k;
+ MPI_CHK( mpi_shift_l( &X, k ) );
+ MPI_CHK( mpi_shift_l( &Y, k ) );
+ }
+ else k = 0;
+
+ n = X.n - 1;
+ t = Y.n - 1;
+ MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
+
+ while ( mpi_cmp_mpi( &X, &Y ) >= 0 )
+ {
+ Z.p[n - t]++;
+ mpi_sub_mpi( &X, &X, &Y );
+ }
+ mpi_shift_r( &Y, biL * (n - t) );
+
+ for ( i = n; i > t ; i-- )
+ {
+ if ( X.p[i] >= Y.p[t] )
+ Z.p[i - t - 1] = ~0;
+ else
+ {
+#if defined(POLARSSL_HAVE_UDBL)
+ t_udbl r;
+
+ r = (t_udbl) X.p[i] << biL;
+ r |= (t_udbl) X.p[i - 1];
+ r /= Y.p[t];
+ if ( r > ((t_udbl) 1 << biL) - 1)
+ r = ((t_udbl) 1 << biL) - 1;
+
+ Z.p[i - t - 1] = (t_uint) r;
+#else
+ /*
+ * __udiv_qrnnd_c, from gmp/longlong.h
+ */
+ t_uint q0, q1, r0, r1;
+ t_uint d0, d1, d, m;
+
+ d = Y.p[t];
+ d0 = ( d << biH ) >> biH;
+ d1 = ( d >> biH );
+
+ q1 = X.p[i] / d1;
+ r1 = X.p[i] - d1 * q1;
+ r1 <<= biH;
+ r1 |= ( X.p[i - 1] >> biH );
+
+ m = q1 * d0;
+ if ( r1 < m )
+ {
+ q1--, r1 += d;
+ while ( r1 >= d && r1 < m )
+ q1--, r1 += d;
+ }
+ r1 -= m;
+
+ q0 = r1 / d1;
+ r0 = r1 - d1 * q0;
+ r0 <<= biH;
+ r0 |= ( X.p[i - 1] << biH ) >> biH;
+
+ m = q0 * d0;
+ if ( r0 < m )
+ {
+ q0--, r0 += d;
+ while ( r0 >= d && r0 < m )
+ q0--, r0 += d;
+ }
+ r0 -= m;
+
+ Z.p[i - t - 1] = ( q1 << biH ) | q0;
+#endif
+ }
+
+ Z.p[i - t - 1]++;
+ do
+ {
+ Z.p[i - t - 1]--;
+
+ MPI_CHK( mpi_lset( &T1, 0 ) );
+ T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+ T1.p[1] = Y.p[t];
+ MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+ MPI_CHK( mpi_lset( &T2, 0 ) );
+ T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+ T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+ T2.p[2] = X.p[i];
+ }
+ while ( mpi_cmp_mpi( &T1, &T2 ) > 0 ) ;
+
+ MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
+
+ if ( mpi_cmp_int( &X, 0 ) < 0 )
+ {
+ MPI_CHK( mpi_copy( &T1, &Y ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
+ Z.p[i - t - 1]--;
+ }
+ }
+
+ if ( Q != NULL )
+ {
+ mpi_copy( Q, &Z );
+ Q->s = A->s * B->s;
+ }
+
+ if ( R != NULL )
+ {
+ mpi_shift_r( &X, k );
+ X.s = A->s;
+ mpi_copy( R, &X );
+
+ if ( mpi_cmp_int( R, 0 ) == 0 )
+ R->s = 1;
+ }
+
+cleanup:
+
+ mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
+ mpi_free( &T1 ); mpi_free( &T2 );
+
+ return( ret );
+}
+/*
+ * Modulo: R = A mod B
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
+{
+ int ret;
+
+ if ( mpi_cmp_int( B, 0 ) < 0 )
+ return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+ MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
+
+ while ( mpi_cmp_int( R, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( R, R, B ) );
+
+ while ( mpi_cmp_mpi( R, B ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
+{
+ size_t i;
+ t_uint x, y, z;
+
+ if ( b == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ if ( b < 0 )
+ return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+ /*
+ * handle trivial cases
+ */
+ if ( b == 1 )
+ {
+ *r = 0;
+ return( 0 );
+ }
+
+ if ( b == 2 )
+ {
+ *r = A->p[0] & 1;
+ return( 0 );
+ }
+
+ /*
+ * general case
+ */
+ for ( i = A->n, y = 0; i > 0; i-- )
+ {
+ x = A->p[i - 1];
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+
+ x <<= biH;
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+ }
+
+ /*
+ * If A is negative, then the current y represents a negative value.
+ * Flipping it to the positive side.
+ */
+ if ( A->s < 0 && y != 0 )
+ y = b - y;
+
+ *r = y;
+
+ return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( t_uint *mm, const mpi *N )
+{
+ t_uint x, m0 = N->p[0];
+
+ x = m0;
+ x += ( ( m0 + 2 ) & 4 ) << 1;
+ x *= ( 2 - ( m0 * x ) );
+
+ if ( biL >= 16 ) x *= ( 2 - ( m0 * x ) ) ;
+ if ( biL >= 32 ) x *= ( 2 - ( m0 * x ) ) ;
+ if ( biL >= 64 ) x *= ( 2 - ( m0 * x ) ) ;
+
+ *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
+ */
+static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
+{
+ size_t i, n, m;
+ t_uint u0, u1, *d;
+
+ memset( T->p, 0, T->n * ciL );
+
+ d = T->p;
+ n = N->n;
+ m = ( B->n < n ) ? B->n : n;
+
+ for ( i = 0; i < n; i++ )
+ {
+ /*
+ * T = (T + u0*B + u1*N) / 2^biL
+ */
+ u0 = A->p[i];
+ u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+ mpi_mul_hlp( m, B->p, d, u0 );
+ mpi_mul_hlp( n, N->p, d, u1 );
+
+ *d++ = u0; d[n + 1] = 0;
+ }
+
+ memcpy( A->p, d, (n + 1) * ciL );
+
+ if ( mpi_cmp_abs( A, N ) >= 0 )
+ mpi_sub_hlp( n, N->p, A->p );
+ else
+ /* prevent timing attacks */
+ mpi_sub_hlp( n, A->p, T->p );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
+{
+ t_uint z = 1;
+ mpi U;
+
+ U.n = U.s = (int) z;
+ U.p = &z;
+
+ mpi_montmul( A, &U, N, mm, T );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
+{
+ int ret;
+ size_t wbits, wsize, one = 1;
+ size_t i, j, nblimbs;
+ size_t bufsize, nbits;
+ t_uint ei, mm, state;
+ mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
+ int neg;
+
+ if ( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ if ( mpi_cmp_int( E, 0 ) < 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ /*
+ * Init temps and window size
+ */
+ mpi_montg_init( &mm, N );
+ mpi_init( &RR ); mpi_init( &T );
+ memset( W, 0, sizeof( W ) );
+
+ i = mpi_msb( E );
+
+ wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+ ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
+
+ if ( wsize > POLARSSL_MPI_WINDOW_SIZE )
+ wsize = POLARSSL_MPI_WINDOW_SIZE;
+
+ j = N->n + 1;
+ MPI_CHK( mpi_grow( X, j ) );
+ MPI_CHK( mpi_grow( &W[1], j ) );
+ MPI_CHK( mpi_grow( &T, j * 2 ) );
+
+ /*
+ * Compensate for negative A (and correct at the end)
+ */
+ neg = ( A->s == -1 );
+
+ mpi_init( &Apos );
+ if ( neg )
+ {
+ MPI_CHK( mpi_copy( &Apos, A ) );
+ Apos.s = 1;
+ A = &Apos;
+ }
+
+ /*
+ * If 1st call, pre-compute R^2 mod N
+ */
+ if ( _RR == NULL || _RR->p == NULL )
+ {
+ MPI_CHK( mpi_lset( &RR, 1 ) );
+ MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
+ MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
+
+ if ( _RR != NULL )
+ memcpy( _RR, &RR, sizeof( mpi ) );
+ }
+ else
+ memcpy( &RR, _RR, sizeof( mpi ) );
+
+ /*
+ * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+ */
+ if ( mpi_cmp_mpi( A, N ) >= 0 )
+ mpi_mod_mpi( &W[1], A, N );
+ else mpi_copy( &W[1], A );
+
+ mpi_montmul( &W[1], &RR, N, mm, &T );
+
+ /*
+ * X = R^2 * R^-1 mod N = R mod N
+ */
+ MPI_CHK( mpi_copy( X, &RR ) );
+ mpi_montred( X, N, mm, &T );
+
+ if ( wsize > 1 )
+ {
+ /*
+ * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+ */
+ j = one << (wsize - 1);
+
+ MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[j], &W[1] ) );
+
+ for ( i = 0; i < wsize - 1; i++ )
+ mpi_montmul( &W[j], &W[j], N, mm, &T );
+
+ /*
+ * W[i] = W[i - 1] * W[1]
+ */
+ for ( i = j + 1; i < (one << wsize); i++ )
+ {
+ MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
+
+ mpi_montmul( &W[i], &W[1], N, mm, &T );
+ }
+ }
+
+ nblimbs = E->n;
+ bufsize = 0;
+ nbits = 0;
+ wbits = 0;
+ state = 0;
+
+ while ( 1 )
+ {
+ if ( bufsize == 0 )
+ {
+ if ( nblimbs-- == 0 )
+ break;
+
+ bufsize = sizeof( t_uint ) << 3;
+ }
+
+ bufsize--;
+
+ ei = (E->p[nblimbs] >> bufsize) & 1;
+
+ /*
+ * skip leading 0s
+ */
+ if ( ei == 0 && state == 0 )
+ continue;
+
+ if ( ei == 0 && state == 1 )
+ {
+ /*
+ * out of window, square X
+ */
+ mpi_montmul( X, X, N, mm, &T );
+ continue;
+ }
+
+ /*
+ * add ei to current window
+ */
+ state = 2;
+
+ nbits++;
+ wbits |= (ei << (wsize - nbits));
+
+ if ( nbits == wsize )
+ {
+ /*
+ * X = X^wsize R^-1 mod N
+ */
+ for ( i = 0; i < wsize; i++ )
+ mpi_montmul( X, X, N, mm, &T );
+
+ /*
+ * X = X * W[wbits] R^-1 mod N
+ */
+ mpi_montmul( X, &W[wbits], N, mm, &T );
+
+ state--;
+ nbits = 0;
+ wbits = 0;
+ }
+ }
+
+ /*
+ * process the remaining bits
+ */
+ for ( i = 0; i < nbits; i++ )
+ {
+ mpi_montmul( X, X, N, mm, &T );
+
+ wbits <<= 1;
+
+ if ( (wbits & (one << wsize)) != 0 )
+ mpi_montmul( X, &W[1], N, mm, &T );
+ }
+
+ /*
+ * X = A^E * R * R^-1 mod N = A^E mod N
+ */
+ mpi_montred( X, N, mm, &T );
+
+ if ( neg )
+ {
+ X->s = -1;
+ mpi_add_mpi( X, N, X );
+ }
+
+cleanup:
+
+ for ( i = (one << (wsize - 1)); i < (one << wsize); i++ )
+ mpi_free( &W[i] );
+
+ mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
+
+ if ( _RR == NULL )
+ mpi_free( &RR );
+
+ return( ret );
+}
+
+#endif
diff --git a/plat/gxb/crypto/ndma_utils.c b/plat/gxb/crypto/ndma_utils.c
new file mode 100644
index 0000000..29147e0
--- /dev/null
+++ b/plat/gxb/crypto/ndma_utils.c
@@ -0,0 +1,183 @@
+#include <stdint.h>
+#include "ndma_utils.h"
+#include <asm/arch/secure_apb.h>
+#include <arch_helpers.h>
+
+uint32_t NDMA_table_ptr_start[4];
+uint32_t NDMA_table_ptr_curr[4];
+uint32_t NDMA_table_ptr_end[4];
+
+
+#define NDMA_Wr(addr, data) *(volatile uint32_t *)(addr)=(data)
+#define NDMA_Rd(addr) *(volatile uint32_t *)(addr)
+// --------------------------------------------
+// NDMA_set_table_position_secure
+// --------------------------------------------
+void NDMA_set_table_position_secure( uint32_t thread_num, uint32_t table_start, uint32_t table_end )
+{
+ NDMA_table_ptr_start[thread_num] = table_start;
+ NDMA_table_ptr_curr[thread_num] = table_start;
+ NDMA_table_ptr_end[thread_num] = table_end;
+ switch ( thread_num ) {
+ case 3: NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_START3, table_start );
+ NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_END3, table_end );
+ // Pulse thread init to register the new start/end locations
+ NDMA_Wr( NDMA_THREAD_REG, NDMA_Rd(NDMA_THREAD_REG) | (1 << 27) );
+ break;
+ case 2: NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_START2, table_start );
+ NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_END2, table_end );
+ // Pulse thread init to register the new start/end locations
+ NDMA_Wr( NDMA_THREAD_REG, NDMA_Rd(NDMA_THREAD_REG) | (1 << 26) );
+ break;
+ case 1: NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_START1, table_start );
+ NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_END1, table_end );
+ // Pulse thread init to register the new start/end locations
+ NDMA_Wr( NDMA_THREAD_REG, NDMA_Rd(NDMA_THREAD_REG) | (1 << 25) );
+ break;
+ case 0: NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_START0, table_start );
+ NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_END0, table_end );
+ // Pulse thread init to register the new start/end locations
+ NDMA_Wr( SEC_NDMA_THREAD_REG, NDMA_Rd(NDMA_THREAD_REG) | (1 << 24) );
+ break;
+ }
+}
+
+
+// --------------------------------------------
+// NDMA_start()
+// --------------------------------------------
+// Start the block move procedure
+//
+void NDMA_start(uint32_t thread_num)
+{
+ NDMA_Wr(SEC_NDMA_CNTL_REG0,NDMA_Rd(SEC_NDMA_CNTL_REG0) | (1 << NDMA_ENABLE) );
+
+ // NDMA_Wr(NDMA_CNTL_REG0,0xf8634000 );
+ NDMA_Wr(SEC_NDMA_THREAD_REG,NDMA_Rd(SEC_NDMA_THREAD_REG) | (1 << (thread_num + 8)) );
+}
+// --------------------------------------------
+// NDMA_wait_for_completion()
+// --------------------------------------------
+// Wait for all block moves to complete
+//
+void NDMA_wait_for_completion(uint32_t thread_num)
+{
+ if ( !NDMA_table_ptr_start[thread_num] ) { // there are no table entries
+ return;
+ }
+
+ while ( (NDMA_Rd(SEC_NDMA_TABLE_ADD_REG) & (0xFF << (thread_num*8))) ) { }
+}
+
+void NDMA_stop(uint32_t thread_num)
+{
+ NDMA_Wr(NDMA_THREAD_REG,NDMA_Rd(NDMA_THREAD_REG) & ~(1 << (thread_num + 8)) );
+ // If no threads enabled, then shut down the DMA engine completely
+ if ( !(NDMA_Rd(NDMA_THREAD_REG) & (0xF << 8)) ) {
+ NDMA_Wr(NDMA_CNTL_REG0,NDMA_Rd(NDMA_CNTL_REG0) & ~(1 << NDMA_ENABLE) );
+ }
+}
+// --------------------------------------------
+// NDMA_add_descriptor_aes
+// --------------------------------------------
+// Simple add function for AES
+void NDMA_add_descriptor_aes(
+uint32_t thread_num,
+uint32_t irq,
+uint32_t cbc_enable,
+uint32_t cbc_reset,
+uint32_t encrypt, // 0 = decrypt, 1 = encrypt
+uint32_t aes_type, // 00 = 128, 01 = 192, 10 = 256
+uint32_t pre_endian,
+uint32_t post_endian,
+uint32_t bytes_to_move,
+uint32_t src_addr,
+uint32_t dest_addr,
+uint32_t ctr_endian,
+uint32_t ctr_limit )
+{
+ volatile uint32_t *p = (volatile uint32_t *)(unsigned long)NDMA_table_ptr_curr[thread_num];
+ (*p++) = (0x01 << 30) | // owned by CPU
+ (0 << 27) |
+ (0 << 26) |
+ (0 << 25) |
+ (4 << 22) | // AES
+ (irq << 21)| (1<<8);
+ (*p++) = src_addr;
+ (*p++) = dest_addr;
+ (*p++) = bytes_to_move & 0x01FFFFFF;
+ (*p++) = 0x00000000; // no skip
+ (*p++) = 0x00000000; // no skip
+ // Prepare the pointer for the next descriptor boundary
+ // inline processing + bytes to move extension
+ (*p++) =
+ (ctr_endian << 16) |
+ (ctr_limit << 14) |
+ (cbc_enable << 12) |
+ (cbc_reset << 11) |
+ (encrypt << 10) |
+ (aes_type << 8) |
+ (post_endian << 4) |
+ (pre_endian << 0);
+
+ #if 0
+ _clean_dcache_addr(NDMA_table_ptr_curr[thread_num]);
+ _clean_invd_dcache_addr (NDMA_table_ptr_curr[thread_num]);
+ _clean_dcache_addr(NDMA_table_ptr_curr[thread_num]+32);
+ _clean_invd_dcache_addr (NDMA_table_ptr_curr[thread_num]+32);
+ #endif
+
+ if ( NDMA_table_ptr_curr[thread_num] == NDMA_table_ptr_end[thread_num] ) {
+ NDMA_table_ptr_curr[thread_num] = NDMA_table_ptr_start[thread_num];
+ } else {
+ NDMA_table_ptr_curr[thread_num] += 32; // point to the next location (8-4 byte table entries)
+ }
+ NDMA_Wr( NDMA_TABLE_ADD_REG, (thread_num << 8) | (1 << 0) );
+}
+
+// --------------------------------------------
+// NDMA_add_descriptor_sha
+// --------------------------------------------
+// Simple add function for SHA
+void NDMA_add_descriptor_sha(
+uint32_t thread_num,
+uint32_t irq,
+uint32_t sha_mode, // 1:sha1;2:sha2-256;3:sha2_224
+uint32_t pre_endian,
+uint32_t bytes_to_move,
+uint32_t src_addr,
+uint32_t last_block )
+{
+ volatile uint32_t *p = (volatile uint32_t *)(unsigned long)NDMA_table_ptr_curr[thread_num];
+ (*p++) = (0x01 << 30) | // owned by CPU
+ (0 << 27) |
+ (0 << 26) |
+ (0 << 25) |
+ (5 << 22) | // SHA
+ (irq << 21) ;
+ (*p++) = src_addr;
+ (*p++) = 0x00000000;
+ (*p++) = bytes_to_move & 0x01FFFFFF;
+ (*p++) = 0x00000000; // no skip
+ (*p++) = 0x00000000; // no skip
+ // Prepare the pointer for the next descriptor boundary
+ // inline processing + bytes to move extension
+ (*p++) = (sha_mode << 8) |
+ (last_block << 4) |
+ (pre_endian << 0);
+
+ #if 0
+ _clean_dcache_addr(NDMA_table_ptr_curr[thread_num]);
+ _clean_invd_dcache_addr (NDMA_table_ptr_curr[thread_num]);
+ _clean_dcache_addr(NDMA_table_ptr_curr[thread_num]+32);
+ _clean_invd_dcache_addr (NDMA_table_ptr_curr[thread_num]+32);
+ #endif
+
+ if ( NDMA_table_ptr_curr[thread_num] == NDMA_table_ptr_end[thread_num] ) {
+ NDMA_table_ptr_curr[thread_num] = NDMA_table_ptr_start[thread_num];
+ } else {
+ NDMA_table_ptr_curr[thread_num] += 32; // point to the next location (8-4 byte table entries)
+ }
+ NDMA_Wr( SEC_NDMA_TABLE_ADD_REG, (thread_num << 8) | (1 << 0) );
+}
+
diff --git a/plat/gxb/crypto/rsa.c b/plat/gxb/crypto/rsa.c
new file mode 100644
index 0000000..988dec3
--- /dev/null
+++ b/plat/gxb/crypto/rsa.c
@@ -0,0 +1,240 @@
+/*
+ * The RSA public-key cryptosystem
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
+ *
+ * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
+ */
+
+#include <rsa_config.h>
+#include <string.h>
+
+#if defined(POLARSSL_RSA_C)
+
+#include <rsa.h>
+
+#include <stdio.h>
+
+/*
+ * Initialize an RSA context
+ */
+
+extern void mymallocreset();
+
+void rsa_init( rsa_context *ctx,
+ int padding,
+ int hash_id )
+{
+ memset( ctx, 0, sizeof( rsa_context ) );
+
+ ctx->padding = padding;
+ ctx->hash_id = hash_id;
+
+ mymallocreset();
+}
+
+/*
+ * Do an RSA public key operation
+ */
+int rsa_public( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t olen;
+ mpi T;
+ mpi_init( &T );
+ MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+ if ( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ mpi_free( &T );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+ olen = ctx->len;
+ MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
+ MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+ mpi_free( &T );
+
+ if ( ret != 0 )
+ return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret );
+ return( 0 );
+}
+
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
+ */
+int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ int ret;
+ size_t len, siglen;
+ unsigned char *p, c;
+ unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+
+ if ( ctx->padding != RSA_PKCS_V15 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ siglen = ctx->len;
+
+ if ( siglen < 16 || siglen > sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+#ifdef CONFIG_EMU_BUILD
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, buf )
+ : rsa_private( ctx, sig, buf );
+#else
+ if (mode != RSA_PUBLIC)
+ return ( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = rsa_public( ctx, sig, buf );
+#endif /* CONFIG_EMU_BUILD */
+
+ if ( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ if ( *p++ != 0 || *p++ != RSA_SIGN )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ while ( *p != 0 )
+ {
+ if ( p >= buf + siglen - 1 || *p != 0xFF )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ p++;
+ }
+ p++;
+
+ len = siglen - ( p - buf );
+
+ if ( len == 33 && hash_id == SIG_RSA_SHA1 )
+ {
+ if ( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 &&
+ memcmp( p + 13, hash, 20 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ if ( len == 34 )
+ {
+ c = p[13];
+ p[13] = 0;
+
+ if ( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+ if ( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
+ ( c == 4 && hash_id == SIG_RSA_MD4 ) ||
+ ( c == 5 && hash_id == SIG_RSA_MD5 ) )
+ {
+ if ( memcmp( p + 18, hash, 16 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ }
+
+ if ( len == 35 && hash_id == SIG_RSA_SHA1 )
+ {
+ if ( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
+ memcmp( p + 15, hash, 20 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ if ( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
+ ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
+ ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
+ ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
+ {
+ c = p[1] - 17;
+ p[1] = 17;
+ p[14] = 0;
+
+ if( p[18] == c &&
+ memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
+ memcmp( p + 19, hash, c ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+
+ if ( len == hashlen && hash_id == SIG_RSA_RAW )
+ {
+ if ( memcmp( p, hash, hashlen ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+}
+
+/*
+ * Do an RSA operation and check the message digest
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ int ret;
+ switch ( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+ ret = rsa_rsassa_pkcs1_v15_verify( ctx, mode, hash_id,
+ hashlen, hash, sig );
+ break;
+ default:
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ return ret;
+}
+
+/*
+ * Free the components of an RSA key
+ */
+void rsa_free( rsa_context *ctx )
+{
+ mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
+ mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
+ mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D );
+ mpi_free( &ctx->E ); mpi_free( &ctx->N );
+}
+
+#endif
diff --git a/plat/gxb/crypto/secureboot.c b/plat/gxb/crypto/secureboot.c
new file mode 100644
index 0000000..fc36dd7
--- /dev/null
+++ b/plat/gxb/crypto/secureboot.c
@@ -0,0 +1,749 @@
+
+/*
+ * arch/arm/cpu/armv8/common/firmware/common/plat/gxb/crypto/secureboot.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+//for polarssl RSA
+#include <rsa.h>
+#include <string.h>
+#include <stdio.h>
+#include <sha2.h>
+#include <asm/arch/secure_apb.h>
+#include <arch_helpers.h>
+
+#include <ndma_utils.h>
+
+//#define AML_DEBUG_SHOW
+
+#if defined(AML_DEBUG_SHOW)
+ #define aml_printf printf
+#else
+ #define aml_printf(...)
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////
+//following code will be used for romcode
+//only signature check
+//
+//////////////////////////////////////////////////////////////////////////////////////
+//following code will be used for romcode
+//only signature check
+//copy from here...
+//return 0 for success, others for fail
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//amlogic secure boot solution
+typedef enum{
+ AML_SIG_TYPE_NONE=0,
+ AML_SIG_TYPE_RSA_PKCS_V15,
+ AML_SIG_TYPE_RSA_PKCS_V21, //??
+ AML_SIG_TYPE_RSA_PKCS_V15_AES,
+}e_aml_sig_type;
+
+typedef enum{
+ AML_DATA_TYPE_NONE=0,
+ AML_DATA_TYPE_RSA_KEY,
+ AML_DATA_TYPE_AES_KEY,
+ AML_DATA_TYPE_PROGRAM_GO, //need this?
+ AML_DATA_TYPE_PROGRAM_CALL, //need this?
+}e_aml_data_type;
+
+
+#define AML_BLK_ID (0x4C4D4140)
+#define AML_BLK_VER_MJR (1)
+#define AML_BLK_VER_MIN (0)
+
+
+typedef struct __st_aml_block_header{
+ //16
+ unsigned int dwMagic; //"@AML"
+ unsigned int nTotalSize; //total size: sizeof(hdr)+
+ // nSigLen + nDataLen
+ unsigned char bySizeHdr; //sizeof(st_aml_block)
+ unsigned char byRootKeyIndex;//root key index; only romcode
+ // will use it, others just skip
+ unsigned char byVerMajor; //major version
+ unsigned char byVerMinor; //minor version
+
+ unsigned char szPadding1[4]; //padding???
+
+ //16+16
+ unsigned int nSigType; //e_aml_sig_type : AML_SIG_TYPE_NONE...
+ unsigned int nSigOffset; //sig data offset, include header
+ unsigned int nSigLen; //sig data length
+ //unsigned char szPadding2[4]; //padding???
+ unsigned int nCHKStart; //begin to be protected with SHA2
+
+ //32+16
+ unsigned int nPUKType; //e_aml_data_type : AML_DATA_TYPE_PROGRAM
+ unsigned int nPUKOffset; //raw data offset, include header
+ unsigned int nPUKDataLen; //raw data length
+ //unsigned char szPadding4[4]; //padding???
+ unsigned int nCHKSize; //size to be protected with SHA2
+
+ //48+16
+ unsigned int nDataType; //e_aml_data_type : AML_DATA_TYPE_PROGRAM
+ unsigned int nDataOffset; //raw data offset, include header
+ unsigned int nDataLen; //raw data length
+ unsigned char szPadding3[4]; //padding???
+
+ //64
+} st_aml_block_header;
+
+typedef enum{
+ AML_ITEM_TYPE_NONE=0,
+ AML_ITEM_TYPE_RAW_RSA_N,
+ AML_ITEM_TYPE_RAW_RSA_E,
+ AML_ITEM_TYPE_RAW_RSA_D,
+}e_aml_big_num_type;
+
+
+typedef struct __stBigNumber{
+ //8
+ unsigned short nBigNMType; //e_aml_big_num_type
+ unsigned short nOffset; //offset for each data, after HDR
+ unsigned short nSize; //size of raw data
+ unsigned char szReserved[2]; //for future ? padding
+ //unsigned char szSHA2Item[32];//SHA2 of raw data ?? need this ??
+ //8
+}st_BIG_NUMBER;
+
+typedef struct __stBigNumberStore{
+ //8
+ unsigned short nBigNMType; //e_aml_big_num_type
+ unsigned short nOffset; //offset for each data, after HDR
+ unsigned short nSize; //size of raw data
+ unsigned char szReserved[2]; //for future ? padding
+ unsigned char pBuffer[1024];
+ //unsigned char szSHA2Item[32];//SHA2 of raw data ?? need this ??
+ //8
+}st_BIG_NUMBER_store;
+
+typedef enum{
+ AML_RSA_TYPE_NONE=0,
+ AML_RSA_TYPE_1024,
+ AML_RSA_TYPE_2048,
+ AML_RSA_TYPE_4096,
+ AML_RSA_TYPE_8192,
+ AML_RSA_TYPE_1024_SHA2,
+ AML_RSA_TYPE_2048_SHA2,
+ AML_RSA_TYPE_4096_SHA2,
+ AML_RSA_TYPE_8192_SHA2,
+
+}e_aml_rsa_type_t;
+
+typedef struct __stItemHeader{
+ //4
+ unsigned char byCount; //amount
+ unsigned char byUnitSize; //sizeof(st_BIG_NUMBER)
+ unsigned char szPad1[2]; //padding
+
+ //4+12
+ unsigned short nItemsOffset; //arrBNM[]
+ unsigned short nItemTotalSize; //(byCount X byUnitSize)
+ unsigned short nRAWOffset; //arrBNM[]
+ unsigned short nRAWSize; //sum(arrBNM[byCount].nSize)
+ unsigned char szPad2[4]; //padding
+ //16
+}st_ITEM_HDR;
+
+/*
+typedef struct __stItemHeader{
+ st_ITEM_HDR header;
+ //......
+ //......
+ st_BIG_NUMBER arrBNM[];
+}st_ITEM;
+*/
+
+#define AML_KEY_ID (0x59454B40)
+#define AML_KEY_VER (1)
+
+#define AML_KEY_RSA1024 (0x41533152)
+#define AML_KEY_RSA2048 (0x41533252)
+#define AML_KEY_RSA4096 (0x41533452)
+#define AML_KEY_RSA8192 (0x41533852)
+
+#define AML_KEY_RSA1024_SHA (0x41483152)
+#define AML_KEY_RSA2048_SHA (0x41483252)
+#define AML_KEY_RSA4096_SHA (0x41483452)
+#define AML_KEY_RSA8192_SHA (0x41483852)
+
+typedef struct __stKeyHeader{
+ //16
+ unsigned int dwMagic; //"@KEY" 0x59454B40
+ unsigned int nTotalSize; //total size
+ unsigned char byVersion; //version
+ unsigned char byKeyType; //e_aml_rsa_type_t
+ unsigned char byHeadSize; //sizeof(st_KEY_HDR)
+ unsigned char szPad1[1]; //padding
+ unsigned int dwTypeInfo; //
+
+ //16+32
+ union{
+ unsigned char szKeySHA2[32];
+ st_ITEM_HDR itemHdr;
+ }un;
+
+ //48
+}st_KEY_HDR;
+
+#define AML_KEY_MATRIX_ID (0x584D4B40)
+#define AML_KEY_MATRIX_VER (1)
+#define AML_KEY_MAX_KEY_NUM (4)
+
+typedef struct __stKeyMaxHeader{
+ //8
+ unsigned int dwMagic; //"@KMX" 0x584D4B40
+ unsigned char byVersion; //version
+ unsigned char szPad1; //padding
+ unsigned short nHeadSize; //sizeof(st_KEY_MAX_HDR)
+
+ //8+8
+ unsigned int nTotalSize; //nHeadSize + (byCount x byUnitSize)
+ // + sum(arrKeyHdr[byCount].itemHdr.nItemTotalSize)
+ unsigned char byCount; //key amount
+ unsigned char byUnitSize; //sizeof(st_KEY_HDR)
+ unsigned char szPad2[2]; //padding
+
+ //16
+}st_KEY_MAX_HDR;
+
+//----------------------------------------------
+typedef struct __stKeyMax{
+ st_KEY_MAX_HDR header;
+ st_KEY_HDR arrKeyHdr[4];
+}st_KEY_MAX;
+
+
+#if defined(AML_DEBUG_SHOW)
+void aml_u8_printf( unsigned char *p, int size )
+{
+ int i;
+ for (i=0; i<size; i++)
+ printf("%02X%s", p[i], ((i+1) % 16==0) ? "\n" :" ");
+}
+#endif
+
+#if defined(CONFIG_AML_SECURE_UBOOT)
+static int aml_key_match_check_tpl(unsigned char szKeySHA2[32])
+{
+ int nReturn = -1;
+ int i = 0;
+ volatile st_KEY_MAX *pKeyMax = (volatile st_KEY_MAX *)(0xd9000808);
+ for (i = 0;i<pKeyMax->header.byCount;++i)
+ {
+ if (!memcmp(szKeySHA2,(void *)pKeyMax->arrKeyHdr[i].un.szKeySHA2,32))
+ {
+ nReturn = 0;
+ break;
+ }
+ }
+
+ return nReturn;
+}
+int aml_load_rsa_puk(rsa_context *prsa_ctx,
+ unsigned char *pBlock,unsigned char szSHA2[32])
+{
+ int nRet = -1;
+ st_aml_block_header *pblkHdr = (st_aml_block_header *)pBlock;
+ st_KEY_HDR * pkeyHdr = (st_KEY_HDR *)(pBlock + pblkHdr->nPUKOffset);
+ st_ITEM_HDR * pHdr = (st_ITEM_HDR*)&pkeyHdr->un.itemHdr;
+ st_BIG_NUMBER *pBGN = (st_BIG_NUMBER *)(pBlock + pHdr->nItemsOffset);
+ unsigned char *pRAW = (unsigned char *)(pBlock + pHdr->nRAWOffset);
+ mpi *pMPI = 0;
+ int i =0;
+
+ if (!prsa_ctx || !pBlock )
+ goto exit;
+
+ //following is just for this verison pollarssl code
+ //just disable them if use the standard copy
+ //begin
+ //extern int g_nMX_RSA_keyFormat;
+ //g_nMX_RSA_keyFormat = 1;
+ //end
+
+ pblkHdr = (st_aml_block_header *)pBlock;
+ pkeyHdr = (st_KEY_HDR *)(pBlock + pblkHdr->nPUKOffset);
+ pHdr = (st_ITEM_HDR*)&pkeyHdr->un.itemHdr;
+ pBGN = (st_BIG_NUMBER *)(pBlock + pHdr->nItemsOffset);
+ pRAW = (unsigned char *)(pBlock + pHdr->nRAWOffset);
+
+
+ sha2(pRAW,pHdr->nRAWSize,szSHA2,0);
+
+ //u8_printf(pBGN,32);
+ //u8_printf(pRAW,32);
+
+ for ( i = 0;i< pHdr->byCount;++i)
+ {
+ switch (pBGN->nBigNMType)
+ {
+ case AML_ITEM_TYPE_RAW_RSA_N: pMPI = &prsa_ctx->N; break;
+ case AML_ITEM_TYPE_RAW_RSA_E: pMPI = &prsa_ctx->E; break;
+ case AML_ITEM_TYPE_RAW_RSA_D: pMPI = &prsa_ctx->D; break;
+ default: pMPI = 0; break;
+ }
+
+ if (!pMPI)
+ while (1) ;
+
+ mpi_read_binary(pMPI,pRAW,pBGN->nSize);
+
+ pRAW += pBGN->nSize;
+ pBGN += 1;
+ }
+
+ prsa_ctx->len = ( mpi_msb( &prsa_ctx->N ) + 7 ) >> 3;
+
+ switch (prsa_ctx->len)
+ {
+ case 0x80: //R1024
+ case 0x100: //R2048
+ case 0x200: nRet = 0;break; //R4096
+ }
+
+exit:
+
+ return nRet;
+}
+#endif //CONFIG_AML_SECURE_UBOOT
+
+/////////////////////////////////////////////////////////////////////////
+/**
+ * pBuffer : st_aml_block_header + signature data + st_aml_block_header(mirror) + [PUK] + raw data
+ * 1. st_aml_block_header will have offset, length, type for signature data, PUK and raw data
+ * 2. signature data is a PKCS #1 v1.5 RSA signature of SHA256 (st_aml_block_header(mirror) + [PUK] + raw data)
+ * signed with the PUK's corresponding private key.
+ * 3. st_aml_block_header(mirror) is a mirror copy of st_aml_block_header for data consistency
+ * 4. PUK is a RSA Public Key to be used for signature check (PKCSv15 format)
+ * 5. raw data: has two types for romcode
+ * 5.1 1st stage: two keymax : the first is for 4 root key SHA256 and the second is for 4 user key SHA256
+ * 5.2 2nd stage: BL2 raw data
+ * pKeyMax : 4 SHA256 hashes of the keys (N+E)
+ * 1. for 1st stage: pKeyMax is 0 for the root keymax and user keymax check
+ * 2. for 2nd stage: pKeyMax is the user keymax to verify the PUK for BL2 signature
+ * pEntry : offset for BL2 start
+ *
+ * return 0 for success and pEntry is the BL2 start address and all others value for check fail
+*/
+int aml_sig_check_buffer(unsigned long pBuffer,unsigned int *pEntry)
+{
+
+ int nReturn = __LINE__;
+#if defined(CONFIG_AML_SECURE_UBOOT)
+ rsa_context rsa_ctx;
+ unsigned char szPUKSHA2[32];
+ unsigned char *pSig;
+#endif
+
+ int nTick;
+
+//#define AML_SECURE_LOG_TE 1
+
+#if defined(AML_SECURE_LOG_TE)
+ #define AML_GET_TE(a) do{a = *((volatile unsigned int*)0xc1109988);}while(0);
+ unsigned nT1,nT2;
+#else
+ #define AML_GET_TE(...)
+#endif
+
+ unsigned char *pData=0;
+ st_aml_block_header * pBlkHdr = 0;
+ int nBL3XSigFlag = 0;
+ unsigned char szSHA2[32];
+ unsigned char *szAMLBLK= (unsigned char *)(unsigned long)(0x10800000);
+ sha2_ctx sha_ctx;
+ pBlkHdr = (st_aml_block_header *)pBuffer;
+
+ aml_printf("aml log : Ln = %d\n",__LINE__);
+
+ if (AML_BLK_ID != pBlkHdr->dwMagic)
+ goto exit;
+
+ if (AML_BLK_VER_MJR != pBlkHdr->byVerMajor)
+ goto exit;
+ if (AML_BLK_VER_MIN != pBlkHdr->byVerMinor)
+ goto exit;
+
+ if (sizeof(st_aml_block_header) != pBlkHdr->bySizeHdr)
+ goto exit;
+
+ //more check
+ if (sizeof(st_aml_block_header) != pBlkHdr->nSigOffset)
+ goto exit;
+
+ aml_printf("aml log : Ln = %d\n",__LINE__);
+
+ nReturn = __LINE__;
+
+#if defined(CONFIG_AML_SECURE_UBOOT)
+ //RSA key load
+ rsa_init( &rsa_ctx, RSA_PKCS_V15, 0 );
+#endif //CONFIG_AML_SECURE_UBOOT
+
+ switch (pBlkHdr->nSigType)
+ {
+#if defined(CONFIG_AML_SECURE_UBOOT)
+ case AML_RSA_TYPE_1024:
+ case AML_RSA_TYPE_2048:
+ case AML_RSA_TYPE_4096:
+ {
+ switch (pBlkHdr->nSigLen)
+ {
+ case 0x80: //R1024
+ case 0x100: //R2048
+ case 0x200: //R4096
+ {
+ nBL3XSigFlag = 1;
+ if (aml_load_rsa_puk(&rsa_ctx,(unsigned char *)pBuffer,szPUKSHA2))
+ goto exit;
+
+ aml_printf("aml log : PUK is RSA%d\n",(rsa_ctx.len<<3));
+
+ }break;//R4096
+ default: goto exit;
+ }
+ }break;
+#endif //CONFIG_AML_SECURE_UBOOT
+ case AML_RSA_TYPE_NONE:break;
+ default: goto exit;
+ }
+
+ aml_printf("aml log : Ln = %d\n",__LINE__);
+
+ nReturn = __LINE__;
+ //check chip is secure enabled or not
+ //if enabled just fail for next boot device
+ //if(aml_check_secure_set_match(nBL3XSigFlag))
+ // goto exit;
+
+ nTick = 64 - (pBlkHdr->nPUKDataLen & (63));
+ //backup header
+ memcpy((void*)szAMLBLK,(void*)pBuffer,pBlkHdr->nDataOffset);
+ pBlkHdr = (st_aml_block_header *)szAMLBLK;
+
+ flush_dcache_range((unsigned long )szAMLBLK, pBlkHdr->nDataOffset);
+
+ //move original
+ memcpy((void*)pBuffer,(void *)(pBuffer + pBlkHdr->nDataLen),pBlkHdr->nDataOffset);
+
+ flush_dcache_range((unsigned long )pBuffer, pBlkHdr->nDataOffset);
+
+ memcpy((void*)(szAMLBLK+pBlkHdr->nDataOffset),(void*)pBuffer,nTick);
+ flush_dcache_range((unsigned long )(szAMLBLK+pBlkHdr->nDataOffset), nTick);
+
+ aml_printf("aml log : Ln = %d\n",__LINE__);
+
+ pData =(unsigned char *)(szAMLBLK + pBlkHdr->nCHKStart);
+
+#if defined(CONFIG_AML_SECURE_UBOOT)
+ pSig = (unsigned char *)(szAMLBLK + pBlkHdr->nSigOffset);
+#endif //#if defined(CONFIG_AML_SECURE_UBOOT)
+
+ AML_GET_TE(nT1);
+
+ SHA2_init( &sha_ctx, 256);
+ //hash header
+ SHA2_update( &sha_ctx, szAMLBLK, pBlkHdr->bySizeHdr);
+ //skip signature
+ //hash PUK
+ SHA2_update( &sha_ctx, pData, pBlkHdr->nPUKDataLen+nTick);
+ SHA2_final( &sha_ctx, (unsigned char *)(pBuffer+nTick), pBlkHdr->nDataLen-nTick);
+ AML_GET_TE(nT2);
+
+ //flush_dcache_range((unsigned long )sha_ctx.buf,32);
+
+#if defined(AML_SECURE_LOG_TE)
+ printf("aml log : SHA %d (bytes) used %d(us)\n",pBlkHdr->nDataLen+ pBlkHdr->nPUKDataLen +pBlkHdr->bySizeHdr,
+ nT2 - nT1);
+#endif
+
+ memcpy(szSHA2,sha_ctx.buf,32);
+
+ flush_dcache_range((unsigned long )szSHA2,32);
+
+#if defined(AML_DEBUG_SHOW)
+ aml_printf("\naml log : dump cal SHA2 :\n");
+ aml_u8_printf((unsigned char *)szSHA2,32);
+#endif
+
+ if (!nBL3XSigFlag)
+ {
+ aml_printf("aml log : normal check Ln = %d\n",__LINE__);
+ nReturn = memcmp((const void*)szSHA2,
+ (const void*)(szAMLBLK+pBlkHdr->nSigOffset),sizeof(szSHA2));
+
+#if defined(AML_DEBUG_SHOW)
+ aml_printf("\naml log : dump org SHA :\n");
+ aml_u8_printf((unsigned char *)(szAMLBLK+pBlkHdr->nSigOffset),32);
+#endif
+ //if(!nReturn && pEntry)
+ // *pEntry = 0;
+ //else
+ if (nReturn)
+ nReturn = __LINE__;
+
+ goto exit;
+ }
+
+#if defined(CONFIG_AML_SECURE_UBOOT)
+ //verify PUK is valid or not
+ if (aml_key_match_check_tpl(szPUKSHA2))
+ {
+ //error
+ aml_printf("aml log: PUK is not a valid key!\n");
+ nReturn = __LINE__;
+ goto exit;
+ }
+
+ nReturn = rsa_pkcs1_verify( &rsa_ctx, RSA_PUBLIC, SIG_RSA_SHA256,32, szSHA2, pSig );
+
+ if (nReturn)
+ {
+ aml_printf("aml log : Sig check fail! Return = %d\n",nReturn);
+ nReturn = __LINE__;
+ goto exit;
+ }
+ else
+ {
+ aml_printf("aml log : Sig check pass!\n");
+
+ if (pEntry)
+ *pEntry = 0;
+
+ }
+
+ //printf("aml log : RSA-%d check %s!\n",rsa_ctx.len<<3, nReturn ? "fail": "pass");
+ serial_puts("aml log : RSA-");
+ serial_put_dec(rsa_ctx.len<<3);
+ serial_puts(" check ");
+ serial_puts(nReturn ? "fail": "pass");
+ serial_puts("!\n");
+#endif //CONFIG_AML_SECURE_UBOOT
+
+exit:
+
+ return nReturn;
+}
+
+#if defined(CONFIG_AML_SECURE_UBOOT)
+
+//#define CONFIG_AML_HW_AES_PIO
+
+#if defined(CONFIG_AML_HW_AES_PIO)
+void aes_setkey( const uint8_t *key)
+{
+ uint32_t i;
+ uint32_t *key32 = (uint32_t *)key;
+
+ // select aes
+ clrbits_le32(SEC_SEC_BLKMV_GEN_REG0, (3<<12));
+
+ // setup aes 256 cbc decrypto pio
+ writel((2<<18) | (1<<16), SEC_SEC_BLKMV_AES_REG0);
+
+ // aes=4, request pio and wait for grant.
+ writel((1<<4) | 4, SEC_SEC_BLKMV_PIO_CNTL0);
+ while (((readl(SEC_SEC_BLKMV_PIO_CNTL0) >> 31) & 1) == 0);
+
+ // Write the Key
+ for (i=0; i<8; i++) {
+ writel(key32[i], SEC_SEC_BLKMV_PIO_DATA0 + i*4);
+ }
+
+ //set IV
+ for (i=0; i<4; i++) writel(0, SEC_SEC_BLKMV_PIO_DATA8 + i*4);
+
+ // load iv
+ setbits_le32(SEC_SEC_BLKMV_AES_REG0, (1<<1));
+
+}
+
+/**
+ * Perform AES 256 CBC decryption
+ * cpt: array of 16 bytes of cipher text and plain text output
+ */
+void aes_cbc_decrypt(uint32_t *cpt)
+{
+ uint32_t i;
+
+ for (i=0; i<4; i++) writel(cpt[i], SEC_SEC_BLKMV_AES_PIO_W0 + i*4);
+
+ // Wait for the AES process to complete
+ while ((readl(SEC_NDMA_CNTL_REG0) >> 12) & 1) ;
+
+ for (i=0; i<4; i++) cpt[i] = readl(SEC_SEC_BLKMV_PIO_DATA0 + i*4);
+}
+#else
+//HW AES DMA
+#define AES_Wr(addr, data) *(volatile uint32_t *)(addr)=(data)
+#define AES_Rd(addr) *(volatile uint32_t *)(addr)
+#define THREAD0_TABLE_LOC 0x5500000
+int g_n_aes_thread_num = 0;
+void aes_setkey( const uint8_t *key)
+{
+ uint32_t *key32 = (uint32_t *)key;
+
+ g_n_aes_thread_num = 0; //fixed thread number to 0
+
+ AES_Wr( SEC_SEC_BLKMV_PIO_CNTL0, (AES_Rd(SEC_SEC_BLKMV_PIO_CNTL0)| (5<<0)) );
+
+ AES_Wr(SEC_SEC_BLKMV_GEN_REG0, ((AES_Rd(SEC_SEC_BLKMV_GEN_REG0) & ~(0xf << 8)) | (0xf << 8)) );
+ AES_Wr(SEC_SEC_BLKMV_GEN_REG0, ((AES_Rd(SEC_SEC_BLKMV_GEN_REG0) & ~(0xf << 0)) | (0 << 0)) );
+
+ AES_Wr(SEC_SEC_BLKMV_GEN_REG0, ((AES_Rd(SEC_SEC_BLKMV_GEN_REG0) & ~(0xf << 4)) | (0x0<< 4)) ); // only thread 2 can issue Secure transfers
+
+ AES_Wr( SEC_SEC_BLKMV_AES_REG0, (AES_Rd(SEC_SEC_BLKMV_AES_REG0) & ~(0x1 << 3)) );
+ AES_Wr( NDMA_AES_REG0, (AES_Rd(NDMA_AES_REG0) & ~(0x3 << 8)) | (g_n_aes_thread_num << 8) );
+
+ //key
+ AES_Wr( NDMA_AES_KEY_0, (key32[0]) );
+ AES_Wr( NDMA_AES_KEY_1, (key32[1]) );
+ AES_Wr( NDMA_AES_KEY_2, (key32[2]) );
+ AES_Wr( NDMA_AES_KEY_3, (key32[3]) );
+ AES_Wr( NDMA_AES_KEY_4, (key32[4]) );
+ AES_Wr( NDMA_AES_KEY_5, (key32[5]) );
+ AES_Wr( NDMA_AES_KEY_6, (key32[6]) );
+ AES_Wr( NDMA_AES_KEY_7, (key32[7]) );
+
+ //set IV
+ AES_Wr( NDMA_AES_IV_0, 0);
+ AES_Wr( NDMA_AES_IV_1, 0);
+ AES_Wr( NDMA_AES_IV_2, 0);
+ AES_Wr( NDMA_AES_IV_3, 0);
+
+ NDMA_set_table_position_secure( g_n_aes_thread_num, THREAD0_TABLE_LOC, THREAD0_TABLE_LOC + (10*32) ); // 2 thread entries
+
+}
+
+void aes_cbc_decrypt(uint32_t *ct,uint32_t *pt,int nLen)
+{
+ NDMA_add_descriptor_aes( g_n_aes_thread_num, // uint32_t thread_num,
+ 1, // uint32_t irq,
+ 1, // uint32_t cbc_enable,
+ 1, // uint32_t cbc_reset,
+ 0, // uint32_t encrypt, // 0 = decrypt, 1 = encrypt
+ 2, // uint32_t aes_type, // 00 = 128, 01 = 192, 10 = 256
+ 0, // uint32_t pre_endian,
+ 0, // uint32_t post_endian,
+ nLen, // uint32_t bytes_to_move,
+ (unsigned int)(long)ct, // uint32_t src_addr,
+ (unsigned int)(long)pt, // uint32_t dest_addr )
+ 0xf, // uint32_t ctr_endian,
+ 0 ); // uint32_t ctr_limit )
+ NDMA_start(g_n_aes_thread_num);
+
+ NDMA_wait_for_completion(g_n_aes_thread_num);
+
+ NDMA_stop(g_n_aes_thread_num);
+
+}
+
+#endif
+#endif //CONFIG_AML_SECURE_UBOOT
+
+int aml_data_check(unsigned long pBuffer,unsigned long pBufferDST,unsigned int nLength,unsigned int nAESFlag)
+{
+
+#define TOC_HEADER_NAME (0xAA640001)
+#define TOC_HEADER_SERIAL_NUMBER (0x12345678)
+
+#if defined(CONFIG_AML_SECURE_UBOOT)
+ unsigned char szAESKey[32];
+ #if defined(CONFIG_AML_HW_AES_PIO)
+ unsigned int *ct32;
+ int i = 0;
+ #endif
+ unsigned char *pDST= (unsigned char *)(pBufferDST);
+#endif //CONFIG_AML_SECURE_UBOOT
+
+#if defined(AML_DEBUG_SHOW)
+ int nBegin,nEnd;
+#endif
+
+ unsigned int *pCHK = (unsigned int *)pBuffer;
+
+#if defined(AML_DEBUG_SHOW)
+ nBegin = *((volatile unsigned int*)0xc1109988);
+#endif
+
+ if (TOC_HEADER_NAME == *pCHK && TOC_HEADER_SERIAL_NUMBER == *(pCHK+1))
+ {
+ return 0;
+ }
+
+
+#if defined(CONFIG_AML_SECURE_UBOOT)
+
+#if defined(AML_DEBUG_SHOW)
+ aml_printf("aml log : begin dump buffer before AES nTPLAESFlag = %d:\n",nAESFlag);
+ aml_u8_printf((unsigned char *)pBuffer,32);
+#endif
+
+ if (nAESFlag)
+ {
+
+ if (nAESFlag)
+ pCHK = (unsigned int*)pDST;
+
+ sha2((unsigned char *)0xd9000000,16,szAESKey,0);
+ aes_setkey(szAESKey);
+
+#if defined(CONFIG_AML_HW_AES_PIO)
+ //HW AES PIO
+ ct32 = (unsigned int *)pBuffer;
+
+ for (i=0; i<nLength/16; i++)
+ aes_cbc_decrypt(&ct32[i*4]);
+
+ memcpy(pDST,(void*)pBuffer,nLength);
+#else
+ //HW AES DMA
+ aes_cbc_decrypt((unsigned int *)pBuffer,(unsigned int *)pDST,nLength);
+#endif
+ pBuffer = (unsigned long)pDST;
+
+ flush_dcache_range((unsigned long )pDST, nLength);
+
+#if defined(AML_DEBUG_SHOW)
+ nEnd = *((volatile unsigned int*)0xc1109988);
+ aml_printf("aml log : begin dump buffer after AES nTPLAESFlag=%d len=%d time=%dus\n",
+ nAESFlag,nLength,nEnd - nBegin);
+ aml_u8_printf((unsigned char *)pBuffer,32);
+#endif
+ if (TOC_HEADER_NAME == *pCHK && TOC_HEADER_SERIAL_NUMBER == *(pCHK+1))
+ return 0;
+ }
+
+#if defined(AML_DEBUG_SHOW)
+ aml_printf("aml log : begin dump buffer after AES nTPLAESFlag = %d:\n",nAESFlag);
+ aml_u8_printf((unsigned char *)pBuffer,32);
+#endif
+
+#endif //CONFIG_AML_SECURE_UBOOT
+
+ return aml_sig_check_buffer(pBuffer,0);
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////