aboutsummaryrefslogtreecommitdiff
pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#!/usr/bin/python
#
# Copyright (c) 2016, NORDUnet A/S All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# - Redistributions of source code must retain the above copyright notice,
#   this list of conditions and the following disclaimer.
#
# - 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.
#
# - Neither the name of the NORDUnet 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.
"""
Utility to transfer a new firmware to the bootloader.

Example usage:

   ./bin/dfu path/to/firmware.bin

Then reset the Cryptech Alpha board.
"""
import os
import sys
import time
import struct
import serial
import argparse

from binascii import crc32

CHUNK_SIZE = 4096


def parse_args():
    """
    Parse the command line arguments
    """
    parser = argparse.ArgumentParser(description = "Device firmware upgrader",
                                     add_help = True,
                                     formatter_class = argparse.ArgumentDefaultsHelpFormatter,
                                     )

    parser.add_argument('--verbose',
                        dest='verbose',
                        action='store_true', default=False,
                        help='Verbose operation',
                        )

    parser.add_argument('--device',
                        dest='device',
                        default='/dev/ttyUSB0',
                        help='Name of management port USB serial device',
                        )

    # positional argument(s)
    parser.add_argument('filename')

    return parser.parse_args()


def _write(dst, data):
    for i in range(len(data)):
        dst.write(data[i])
        time.sleep(0.1)
    if len(data) == 4:
        print("Wrote 0x{:02x}{:02x}{:02x}{:02x}".format(ord(data[0]), ord(data[1]), ord(data[2]), ord(data[3])))
    else:
        print("Wrote {!r}".format(data))


def _read(dst, verbose=False):
    res = ''
    while True:
        x = dst.read(1)
        if not x:
            break
        res += x
    if res and verbose:
        print ("Read {!r}".format(res))
    return res


def send_file(filename, args):
    s = os.stat(filename)
    size = s.st_size
    src = open(filename, 'rb')
    chunk_size = CHUNK_SIZE

    print("Waiting for contact with the bootloader on device {!s}, reset the CrypTech Alpha...".format(args.device))

    while True:
        try:
            dst = serial.Serial(args.device, 921600, timeout=0.1)
        except serial.SerialException:
            time.sleep(0.2)
            continue
        dst.write('\r')
        response = _read(dst, args.verbose)
        if 'OK' in response:
            dst.timeout=2
            break

    print('\nUploading firmware\n')

    crc = 0
    counter = 0
    # 1. Write size of file (4 bytes)
    _write(dst, struct.pack('<I', size))
    _read(dst, args.verbose)
    # 2. Write file contents while calculating CRC-32
    while True:
        data = src.read(chunk_size)
        if not data:
            break
        dst.write(data)
        print("Wrote {!s} bytes (chunk {!s}/{!s})".format(len(data), counter, int(size / chunk_size)))
        # read ACK (a counter of number of 4k chunks received)
        while True:
            ack_bytes = dst.read(4)
            if len(ack_bytes) == 4:
                break
            print('ERROR: Did not receive an ACK, got {!r}'.format(ack_bytes))
            dst.write('\r')  # eventually get back to the CLI prompt
        ack = struct.unpack('<I', ack_bytes)[0]
        if ack != counter + 1:
            print('ERROR: Did not receive the expected counter as ACK (got {!r}/{!r}, not {!r})'.format(ack, ack_bytes, counter))
            flush = dst.read(100)
            print('FLUSH data: {!r}'.format(flush))
            return False
        counter += 1

        crc = crc32(data, crc) & 0xffffffff

    _read(dst, args.verbose)

    # 3. Write CRC-32 (4 bytes)
    _write(dst, struct.pack('<I', crc))

    if args.verbose:
        print('\nFinished - this command might hang now depending on the firmware loaded')
        _read(dst, args.verbose)
    else:
        print('\nFinished uploading firmware')

    src.close()
    dst.close()
    return True


def main(args):
    send_file(args.filename, args)
    return True

if __name__ == '__main__':
    try:
        args = parse_args()
        if main(args):
            sys.exit(0)
        sys.exit(1)
    except KeyboardInterrupt:
        pass
AgeCommit message (Collapse)Author
2016-03-29Remove unneeded hal_internal.hPaul Selkirk
2016-03-29Add test-rpc_get_randomPaul Selkirk
2016-03-21Merge branch 'master' into rpcPaul Selkirk
2016-03-21stupid fixesPaul Selkirk
2016-03-21Don't build position-independent code for stm32.Paul Selkirk
2016-03-21Skip tests we know are going to fail.Paul Selkirk
2016-03-16Added serial RPC transport and lots more...Paul Selkirk
Added RPC function to get server version number. Substantially reworked GNUMakefile with conditionals. Renamed rpc_*() and xdr_*() to hal_*() for consistency. Moved hal_io_fmc.c from stm32 repo.
2016-03-12Merge branch 'master' into rpcRob Austein
2016-03-12Disable ECDSA static-test-vectors hack, fix call to hal_get_random()Rob Austein
which was using the old (pre-hal_core_t) calling sequence.
2016-03-12Test RPC key generation API.Rob Austein
2016-03-12Doh, helps to specify the curve.Rob Austein
2016-03-12Basic RPC ECDSA tests.Rob Austein
2016-03-11First round of debugging based on RPC pkey tests: mostly ASN.1Rob Austein
silliness, with a bit of PKCS #1.5 padding silliness for desert.
2016-03-11First step towards RPC PKEY tests. Currently RSA-only, test-vectorRob Austein
only, requires AES core (for key wrapping).
2016-03-09Tweak handling of byte swapping in software hash cores to get rid ofRob Austein
some unnecessary data copying.
2016-03-09Optional (compile time conditional) software hash cores. At theRob Austein
moment this is all-or-nothing, but could easily be tweaked to allow compile-time selection of particular hashes.
2016-03-03Initial implementations of ks_get_kek(). Untested, and none of theseRob Austein