aheinecke@452: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
aheinecke@452:  * Software engineering by Intevation GmbH
aheinecke@452:  *
aheinecke@452:  * This file is Free Software under the GNU GPL (v>=2)
aheinecke@452:  * and comes with ABSOLUTELY NO WARRANTY!
aheinecke@452:  * See LICENSE.txt for details.
aheinecke@452:  */
aheinecke@452: #include "sslhelp.h"
aheinecke@464: #include <polarssl/sha256.h>
aheinecke@464: #include <polarssl/pk.h>
aheinecke@464: #include <polarssl/entropy.h>
aheinecke@464: #include <polarssl/ctr_drbg.h>
aheinecke@464: #include <QApplication>
aheinecke@464: #include <QUuid>
aheinecke@464: #include <QDebug>
aheinecke@452: 
aheinecke@452: QString getPolarSSLErrorMsg(int ret)
aheinecke@452: {
aheinecke@452:     char errbuf[1020];
aheinecke@452:     polarssl_strerror(ret, errbuf, 1020);
aheinecke@475:     errbuf[1019] = '\0'; /* Just to be sure */
aheinecke@452:     return QString::fromLatin1(errbuf);
aheinecke@452: }
aheinecke@464: 
aheinecke@464: QByteArray sha256sum(const QByteArray& data)
aheinecke@464: {
aheinecke@464:     unsigned char output[32];
aheinecke@464:     sha256((unsigned char *)data.constData(), (size_t)data.size(), output, 0);
aheinecke@469:     return QByteArray((const char *)output, 32);
aheinecke@464: }
aheinecke@464: 
aheinecke@464: QByteArray rsaSignSHA256Hash(const QByteArray& hash, pk_context *pk)
aheinecke@464: {
aheinecke@464:     int ret = 0;
aheinecke@464:     unsigned char sig[POLARSSL_MPI_MAX_SIZE];
aheinecke@464:     size_t sig_len;
aheinecke@464:     entropy_context entropy;
aheinecke@464:     ctr_drbg_context ctr_drbg;
aheinecke@464: 
aheinecke@464:     entropy_init(&entropy);
aheinecke@464: 
aheinecke@464:     QUuid uuid = QUuid::createUuid();
aheinecke@464:     QString personalString = QApplication::applicationName() + uuid.toString();
aheinecke@464:     QByteArray personalBa = personalString.toLocal8Bit();
aheinecke@464: 
aheinecke@464:     /*
aheinecke@464:     * Initialize random generator.
aheinecke@464:     * Personalisation string, does not need to be random but
aheinecke@464:     * should be unique according to documentation.
aheinecke@464:     *
aheinecke@464:     * the ctr_drbg structure does not need to be freed explicitly.
aheinecke@464:     */
aheinecke@464:     ret = ctr_drbg_init(&ctr_drbg, entropy_func, &entropy,
aheinecke@464:                         (const unsigned char*) personalBa.constData(),
aheinecke@464:                         personalBa.size());
aheinecke@464:     if (ret != 0) {
aheinecke@464:         qDebug() << "Failed to initialize drbg: " << getPolarSSLErrorMsg(ret);
aheinecke@464:         entropy_free (&entropy);
aheinecke@464:         return QByteArray();
aheinecke@464:     }
aheinecke@464: 
aheinecke@464:     ret = pk_sign(pk, POLARSSL_MD_SHA256, (const unsigned char*) hash.constData(),
aheinecke@464:                   hash.size(), sig, &sig_len, ctr_drbg_random, &ctr_drbg);
aheinecke@464:     entropy_free (&entropy);
aheinecke@464: 
aheinecke@464:     if (ret != 0) {
aheinecke@464:         qDebug() << "Failed to sign: " << getPolarSSLErrorMsg(ret);
aheinecke@464:         return QByteArray();
aheinecke@464:     }
aheinecke@464: 
aheinecke@464:     if (sig_len != 3072 / 8) {
aheinecke@464:         qDebug() << "Invalid size of signature: " << sig_len;
aheinecke@464:         return QByteArray();
aheinecke@464:     }
aheinecke@464: 
aheinecke@464:     return QByteArray((const char *)sig, (int)sig_len);
aheinecke@464: }