12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432 |
- /* ssl_bn.c
- *
- * Copyright (C) 2006-2023 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL 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.
- *
- * wolfSSL 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-1335, USA
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <wolfssl/wolfcrypt/settings.h>
- #include <wolfssl/internal.h>
- #ifndef WC_NO_RNG
- #include <wolfssl/wolfcrypt/random.h>
- #endif
- #if !defined(WOLFSSL_SSL_BN_INCLUDED)
- #ifndef WOLFSSL_IGNORE_FILE_WARN
- #warning ssl_bn.c does not need to be compiled separately from ssl.c
- #endif
- #else
- /* Check on validity of big number.
- *
- * Used for parameter validation.
- *
- * @param [in] bn Big number.
- * @return 1 when bn is not NULL and internal representation is not NULL.
- * @return 0 otherwise.
- */
- #define BN_IS_NULL(bn) (((bn) == NULL) || ((bn)->internal == NULL))
- /*******************************************************************************
- * Constructor/Destructor/Initializer APIs
- ******************************************************************************/
- #if defined(OPENSSL_EXTRA) && !defined(NO_ASN)
- /* Set big number to be negative.
- *
- * @param [in, out] bn Big number to make negative.
- * @param [in] neg Whether number is negative.
- * @return 1 on success.
- * @return -1 when bn or internal representation of bn is NULL.
- */
- static int wolfssl_bn_set_neg(WOLFSSL_BIGNUM* bn, int neg)
- {
- int ret = 1;
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = -1;
- }
- #if !defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_INT_NEGATIVE)
- else if (neg) {
- mp_setneg((mp_int*)bn->internal);
- }
- else {
- ((mp_int*)bn->internal)->sign = MP_ZPOS;
- }
- #endif
- return ret;
- }
- #endif /* OPENSSL_EXTRA && !NO_ASN */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- /* Get the internal representation value into an MP integer.
- *
- * When calling wolfssl_bn_get_value, mpi should be cleared by caller if no
- * longer used. ie mp_free(mpi). This is to free data when fastmath is
- * disabled since a copy of mpi is made by this function and placed into bn.
- *
- * @param [in] bn Big number to copy value from.
- * @param [in, out] mpi MP integer to copy into.
- * @return 1 on success.
- * @return -1 when bn or internal representation of bn is NULL.
- * @return -1 when mpi is NULL.
- * @return -1 when copy fails.
- */
- int wolfssl_bn_get_value(WOLFSSL_BIGNUM* bn, mp_int* mpi)
- {
- int ret = 1;
- WOLFSSL_MSG("Entering wolfssl_bn_get_value_mp");
- /* Validate parameters. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = -1;
- }
- else if (mpi == NULL) {
- WOLFSSL_MSG("mpi NULL error");
- ret = -1;
- }
- /* Copy the internal representation into MP integer. */
- if ((ret == 1) && mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- ret = -1;
- }
- return ret;
- }
- /* Set big number internal representation to value in mpi.
- *
- * Will create a new big number if bn points to NULL.
- *
- * When calling wolfssl_bn_set_value, mpi should be cleared by caller if no
- * longer used. ie mp_free(mpi). This is to free data when fastmath is
- * disabled since a copy of mpi is made by this function and placed into bn.
- *
- * @param [in, out] bn Pointer to big number to have value.
- * @param [in] mpi MP integer with value to set.
- * @return 1 on success.
- * @return -1 when mpi or bn is NULL.
- * @return -1 when creating a new big number fails.
- * @return -1 when copying MP integer fails.
- */
- int wolfssl_bn_set_value(WOLFSSL_BIGNUM** bn, mp_int* mpi)
- {
- int ret = 1;
- WOLFSSL_BIGNUM* a = NULL;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfssl_bn_set_value");
- #endif
- /* Validate parameters. */
- if ((bn == NULL) || (mpi == NULL)) {
- WOLFSSL_MSG("mpi or bn NULL error");
- ret = -1;
- }
- /* Allocate a new big number if one not passed in. */
- if ((ret == 1) && (*bn == NULL)) {
- a = wolfSSL_BN_new();
- if (a == NULL) {
- WOLFSSL_MSG("wolfssl_bn_set_value alloc failed");
- ret = -1;
- }
- *bn = a;
- }
- /* Copy MP integer value into internal representation of big number. */
- if ((ret == 1) && (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY)) {
- WOLFSSL_MSG("mp_copy error");
- ret = -1;
- }
- /* Dispose of any allocated big number on error. */
- if ((ret == -1) && (a != NULL)) {
- BN_free(a);
- *bn = NULL;
- }
- return ret;
- }
- /* Initialize a big number.
- *
- * Assumes bn is not NULL.
- *
- * @param [in, out] bn Big number to initialize.
- */
- static void wolfssl_bn_init(WOLFSSL_BIGNUM* bn)
- {
- /* Clear fields of big number. */
- XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM));
- /* Initialization only fails when passed NULL. */
- (void)mp_init(&bn->mpi);
- /* Set an internal representation. */
- bn->internal = &bn->mpi;
- }
- /* Create a new big number.
- *
- * @return An allocated and initialized big number on success.
- * @return NULL on failure.
- */
- WOLFSSL_BIGNUM* wolfSSL_BN_new(void)
- {
- WOLFSSL_BIGNUM* bn = NULL;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_BN_new");
- #endif
- /* Allocate memory for big number. */
- bn = (WOLFSSL_BIGNUM*)XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL,
- DYNAMIC_TYPE_BIGINT);
- if (bn == NULL) {
- WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure");
- }
- else {
- /* Initialize newly allocated object. */
- wolfssl_bn_init(bn);
- }
- return bn;
- }
- #if !defined(USE_INTEGER_HEAP_MATH) && !defined(HAVE_WOLF_BIGINT)
- /* Initialize a big number.
- *
- * Call this instead of wolfSSL_BN_new() and wolfSSL_BN_free().
- *
- * Do not call this API after wolfSSL_BN_new() or wolfSSL_BN_init().
- *
- * @param [in, out] bn Big number to initialize.
- */
- void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_BN_init");
- #endif
- /* Validate parameter. */
- if (bn != NULL) {
- /* Initialize big number object. */
- wolfssl_bn_init(bn);
- }
- }
- #endif
- /* Dispose of big number.
- *
- * bn is unusable after this call.
- *
- * @param [in, out] bn Big number to free.
- */
- void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_BN_free");
- #endif
- /* Validate parameter. */
- if (bn != NULL) {
- /* Cleanup any internal representation. */
- if (bn->internal != NULL) {
- /* Free MP integer. */
- mp_free(&bn->mpi);
- }
- /* Dispose of big number object. */
- XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT);
- /* bn = NULL, don't try to access or double free it */
- }
- }
- /* Zeroize and dispose of big number.
- *
- * bn is unusable after this call.
- *
- * @param [in, out] bn Big number to clear and free.
- */
- void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_BN_clear_free");
- #endif
- /* Validate parameter. */
- if (bn != NULL) {
- /* Check for internal representation. */
- if (bn->internal != NULL) {
- /* Zeroize MP integer. */
- mp_forcezero((mp_int*)bn->internal);
- }
- /* Dispose of big number. */
- wolfSSL_BN_free(bn);
- }
- }
- /* Zeroize big number.
- *
- * @param [in, out] bn Big number to clear.
- */
- void wolfSSL_BN_clear(WOLFSSL_BIGNUM* bn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_BN_clear");
- #endif
- /* Validate parameter. */
- if (!BN_IS_NULL(bn)) {
- /* Zeroize MP integer. */
- mp_forcezero((mp_int*)bn->internal);
- }
- }
- #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- #ifdef OPENSSL_EXTRA
- static WOLFSSL_BIGNUM* bn_one = NULL;
- /* Return a big number with the value of one.
- *
- * @return A big number with the value one on success.
- * @return NULL on failure.
- */
- const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
- {
- WOLFSSL_BIGNUM* one;
- WOLFSSL_ENTER("wolfSSL_BN_value_one");
- /* Get the global object. */
- one = bn_one;
- /* Create a new big number if global not set. */
- if ((one == NULL) && ((one = wolfSSL_BN_new()) != NULL)) {
- /* Set internal representation to have a value of 1. */
- if (mp_set_int((mp_int*)one->internal, 1) != MP_OKAY) {
- /* Dispose of big number on error. */
- wolfSSL_BN_free(one);
- one = NULL;
- }
- else
- #ifndef SINGLE_THREADED
- /* Ensure global has not been set by another thread. */
- if (bn_one == NULL)
- #endif
- {
- /* Set this big number as the global. */
- bn_one = one;
- }
- #ifndef SINGLE_THREADED
- /* Check if another thread has set the global. */
- if (bn_one != one) {
- /* Dispose of this big number and return the global. */
- wolfSSL_BN_free(one);
- one = bn_one;
- }
- #endif
- }
- return one;
- }
- static void wolfSSL_BN_free_one(void) {
- wolfSSL_BN_free(bn_one);
- bn_one = NULL;
- }
- /* Create a new big number with the same value as the one passed in.
- *
- * @param [in] bn Big number to duplicate.
- * @return Big number on success.
- * @return NULL when bn or internal representation of bn is NULL.
- * @return NULL when creating a new big number fails.
- * @return NULL when copying the internal representation fails.
- */
- WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn)
- {
- int err = 0;
- WOLFSSL_BIGNUM* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_BN_dup");
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- err = 1;
- }
- /* Create a new big number to return. */
- if ((!err) && ((ret = wolfSSL_BN_new()) == NULL)) {
- WOLFSSL_MSG("bn new error");
- err = 1;
- }
- if (!err) {
- err = (wolfSSL_BN_copy(ret, bn) == NULL);
- }
- if (err) {
- /* Dispose of dynamically allocated data. */
- wolfSSL_BN_free(ret);
- ret = NULL;
- }
- return ret;
- }
- /* Copy value from bn into another r.
- *
- * @param [in, out] r Big number to copy into.
- * @param [in] bn Big number to copy from.
- * @return Big number copied into on success.
- * @return NULL when r or bn is NULL.
- * @return NULL when copying fails.
- */
- WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_ENTER("wolfSSL_BN_copy");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(bn)) {
- WOLFSSL_MSG("r or bn NULL error");
- r = NULL;
- }
- /* Copy the value in. */
- if ((r != NULL) && mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) !=
- MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- r = NULL;
- }
- if (r != NULL) {
- /* Copy other fields in a big number. */
- r->neg = bn->neg;
- }
- return r;
- }
- /*******************************************************************************
- * Encode/Decode APIs.
- ******************************************************************************/
- /* Encode the number is a big-endian byte array.
- *
- * Assumes byte array is large enough to hold encoding when not NULL.
- * Use NULL for byte array to get length.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] bn Big number to reduced
- * @param [out] r Byte array to encode into. May be NULL.
- * @return Length of big number in bytes on success.
- * @return -1 when bn is NULL or encoding fails.
- */
- int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_bn2bin");
- /* Validate parameters. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("NULL bn error");
- ret = -1;
- }
- else {
- /* Get the length of the encoding. */
- ret = mp_unsigned_bin_size((mp_int*)bn->internal);
- /* Encode if byte array supplied. */
- if ((r != NULL) && (mp_to_unsigned_bin((mp_int*)bn->internal, r) !=
- MP_OKAY)) {
- WOLFSSL_MSG("mp_to_unsigned_bin error");
- ret = -1;
- }
- }
- return ret;
- }
- /* Return a big number with value of the decoding of the big-endian byte array.
- *
- * Returns ret when not NULL.
- * Allocates a big number when ret is NULL.
- * Assumes str is not NULL.
- *
- * @param [in] data Byte array to decode.
- * @param [in] len Number of bytes in byte array.
- * @param [in, out] ret Big number to reduced. May be NULL.
- * @return A big number on success.
- * @return NULL on failure.
- */
- WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* data, int len,
- WOLFSSL_BIGNUM* ret)
- {
- WOLFSSL_BIGNUM* bn = NULL;
- WOLFSSL_ENTER("wolfSSL_BN_bin2bn");
- /* Validate parameters. */
- if ((data == NULL) || (len < 0)) {
- ret = NULL;
- }
- /* Allocate a new big number when ret is NULL. */
- else if (ret == NULL) {
- ret = wolfSSL_BN_new();
- bn = ret;
- }
- /* Check ret is usable. */
- if (ret != NULL) {
- /* Check internal representation is usable. */
- if (ret->internal == NULL) {
- ret = NULL;
- }
- else {
- /* Decode into big number. */
- if (mp_read_unsigned_bin((mp_int*)ret->internal, data, (word32)len)
- != 0) {
- WOLFSSL_MSG("mp_read_unsigned_bin failure");
- /* Don't return anything on failure. bn will be freed if set. */
- ret = NULL;
- }
- else {
- /* Don't free bn as we may be returning it. */
- bn = NULL;
- }
- }
- }
- /* Dispose of allocated BN not being returned. */
- wolfSSL_BN_free(bn);
- return ret;
- }
- /* Encode the big number value into a string, of the radix, that is allocated.
- *
- * @param [in] bn Big number to encode.
- * @param [in] radix Radix to encode to.
- * @return String with encoding on success.
- * @return NULL when bn or internal representation of bn is NULL.
- * @return NULL on failure.
- */
- static char* wolfssl_bn_bn2radix(const WOLFSSL_BIGNUM* bn, int radix)
- {
- int err = 0;
- int len = 0;
- char* str = NULL;
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- err = 1;
- }
- /* Determine length of encoding. */
- if ((!err) && (mp_radix_size((mp_int*)bn->internal, radix, &len) !=
- MP_OKAY)) {
- WOLFSSL_MSG("mp_radix_size failure");
- err = 1;
- }
- if (!err) {
- /* Allocate string. */
- str = (char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_OPENSSL);
- if (str == NULL) {
- WOLFSSL_MSG("BN_bn2hex malloc string failure");
- err = 1;
- }
- }
- /* Encode into string using wolfCrypt. */
- if ((!err) && (mp_toradix((mp_int*)bn->internal, str, radix) != MP_OKAY)) {
- err = 1;
- }
- if (err) {
- /* Dispose of dynamically allocated data. */
- XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL);
- /* Don't return freed string. */
- str = NULL;
- }
- return str;
- }
- /* Encode the big number value into hex string that is allocated.
- *
- * @param [in] bn Big number to encode.
- * @return String with encoding on success.
- * @return NULL when bn or internal representation of bn is NULL.
- * @return NULL on failure.
- */
- char* wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn)
- {
- WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
- return wolfssl_bn_bn2radix(bn, MP_RADIX_HEX);
- }
- /* Decode string of a radix into a big number.
- *
- * If bn is a pointer to NULL, then a new big number is allocated and assigned.
- *
- * Note on use: this function expects str to be an even length. It is
- * converting pairs of bytes into 8-bit values. As an example, the RSA
- * public exponent is commonly 0x010001. To get it to convert, you need
- * to pass in the string "010001", it will fail if you use "10001". This
- * is an affect of how Base16_Decode() works.
- *
- * @param [in, out] bn Pointer to a big number. May point to NULL.
- * @param [in] str Hex string to decode.
- * @param [in] radix Radix to decode from.
- * @return 1 on success.
- * @return 0 when bn or str is NULL or str is zero length.
- * @return 0 when creating a new big number fails.
- * @return 0 when decoding fails.
- */
- static int wolfssl_bn_radix2bn(WOLFSSL_BIGNUM** bn, const char* str, int radix)
- {
- int ret = 1;
- WOLFSSL_BIGNUM* a = NULL;
- /* Validate parameters. */
- if ((bn == NULL) || (str == NULL) || (str[0] == '\0')) {
- WOLFSSL_MSG("Bad function argument");
- ret = 0;
- }
- /* Check if we have a big number to decode into. */
- if ((ret == 1) && (*bn == NULL)) {
- /* Allocate a new big number. */
- a = wolfSSL_BN_new();
- if (a == NULL) {
- WOLFSSL_MSG("BN new failed");
- ret = 0;
- }
- /* Return allocated big number. */
- *bn = a;
- }
- /* Decode hex string into internal representation. */
- if ((ret == 1) && (mp_read_radix((mp_int*)(*bn)->internal, str, radix) !=
- MP_OKAY)) {
- WOLFSSL_MSG("Bad read_radix error");
- ret = 0;
- }
- if ((ret == 0) && (a != NULL)) {
- /* Dispose of big number. */
- wolfSSL_BN_free(a);
- /* Don't return freed big number. */
- *bn = NULL;
- }
- return ret;
- }
- /* Decode hex string into a big number.
- *
- * If bn is a pointer to NULL, then a new big number is allocated and assigned.
- *
- * Note on use: this function expects str to be an even length. It is
- * converting pairs of bytes into 8-bit values. As an example, the RSA
- * public exponent is commonly 0x010001. To get it to convert, you need
- * to pass in the string "010001", it will fail if you use "10001". This
- * is an affect of how Base16_Decode() works.
- *
- * @param [in, out] bn Pointer to a big number. May point to NULL.
- * @param [in] str Hex string to decode.
- * @return 1 on success.
- * @return 0 when bn or str is NULL or str is zero length.
- * @return 0 when creating a new big number fails.
- * @return 0 when decoding fails.
- */
- int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str)
- {
- WOLFSSL_ENTER("wolfSSL_BN_hex2bn");
- return wolfssl_bn_radix2bn(bn, str, MP_RADIX_HEX);
- }
- #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY)
- /* Encode big number into decimal string.
- *
- * @param [in] bn Big number to encode.
- * @return String with encoding on success.
- * @return NULL when bn or internal representation of bn is NULL.
- * @return NULL on failure.
- */
- char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn)
- {
- WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
- return wolfssl_bn_bn2radix(bn, MP_RADIX_DEC);
- }
- #else
- /* Encode big number into decimal string.
- *
- * @param [in] bn Big number to encode.
- * @return NULL as implementation not available.
- */
- char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn)
- {
- (void)bn;
- WOLFSSL_ENTER("wolfSSL_BN_bn2dec");
- return NULL;
- }
- #endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */
- #ifndef NO_RSA
- /* Decode hex string into a big number.
- *
- * If bn is a pointer to NULL, then a new big number is allocated and assigned.
- *
- * Note on use: this function expects str to be an even length. It is
- * converting pairs of bytes into 8-bit values. As an example, the RSA
- * public exponent is commonly 0x010001. To get it to convert, you need
- * to pass in the string "010001", it will fail if you use "10001". This
- * is an affect of how Base16_Decode() works.
- *
- * @param [in, out] bn Pointer to a big number. May point to NULL.
- * @param [in] str Hex string to decode.
- * @return 1 on success.
- * @return 0 when bn or str is NULL or str is zero length.
- * @return 0 when creating a new big number fails.
- * @return 0 when decoding fails.
- */
- int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
- {
- WOLFSSL_ENTER("wolfSSL_BN_bn2dec");
- return wolfssl_bn_radix2bn(bn, str, MP_RADIX_DEC);
- }
- #else
- /* Decode hex string into a big number.
- *
- * @param [in, out] bn Pointer to a big number. May point to NULL.
- * @param [in] str Hex string to decode.
- * @return 0 as implementation not available..
- */
- int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
- {
- (void)bn;
- (void)str;
- WOLFSSL_ENTER("wolfSSL_BN_bn2dec");
- return 0;
- }
- #endif
- /*******************************************************************************
- * Get/Set APIs
- ******************************************************************************/
- /* Calculate the number of bytes need to represent big number.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] bn Big number to use.
- * @return Size of BIGNUM in bytes on success.
- * @return 0 when bn or internal representation of bn is NULL.
- */
- int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_num_bytes");
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- ret = 0;
- }
- else {
- /* Get size from wolfCrypt. */
- ret = mp_unsigned_bin_size((mp_int*)bn->internal);
- }
- return ret;
- }
- /* Calculate the number of bits need to represent big number.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] bn Big number to use.
- * @return Size of BIGNUM in bits on success.
- * @return 0 when bn or internal representation of bn is NULL.
- */
- int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_num_bits");
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- ret = 0;
- }
- else {
- /* Get size from wolfCrypt. */
- ret = mp_count_bits((mp_int*)bn->internal);
- }
- return ret;
- }
- /* Indicates whether a big number is negative.
- *
- * @param [in] bn Big number to use.
- * @return 1 when number is negative.
- * @return 0 when number is positive.
- * @return 0 when bn is NULL.
- */
- int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn)
- {
- int ret;
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- ret = 0;
- }
- else {
- /* Check sign with wolfCrypt. */
- ret = mp_isneg((mp_int*)bn->internal);
- }
- return ret;
- }
- /* Indicates whether a big number is odd.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] bn Big number to use.
- * @return 1 when number is odd.
- * @return 0 when number is even.
- * @return 0 when bn or internal representation of bn is NULL.
- */
- int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_is_odd");
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- ret = 0;
- }
- else {
- /* wolfCrypt checks whether value is odd. */
- ret = (mp_isodd((mp_int*)bn->internal) == MP_YES);
- }
- return ret;
- }
- #ifndef NO_WOLFSSL_STUB
- /* Mask the lowest n bits.
- *
- * TODO: mp_mod_2d()
- *
- * Return compliant with OpenSSL.
- *
- * @param [in, out] bn Big number to operation on.
- * @param [in] n Number of bits.
- * @return 0 on failure.
- */
- int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n)
- {
- (void)bn;
- (void)n;
- WOLFSSL_ENTER("wolfSSL_BN_mask_bits");
- WOLFSSL_STUB("BN_mask_bits");
- return 0;
- }
- #endif
- /* Set a bit of the value in a big number.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in, out] bn Big number to modify.
- * @return 1 on success.
- * @return 0 when bn or internal representation of bn is NULL.
- * @return 0 when failed to set bit.
- */
- int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n)
- {
- int ret = 1;
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- else if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) {
- WOLFSSL_MSG("mp_set_bit error");
- ret = 0;
- }
- return ret;
- }
- /* Clear a bit of the value in a big number.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] bn Big number to check.
- * @param [in] n Inidex of bit to check.
- * @return 1 on success.
- * @return 0 when bn or internal representation of bn is NULL.
- * @return 0 when failed to clear bit.
- */
- int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n)
- {
- int ret = 1;
- #ifndef WOLFSSL_SMALL_STACK
- mp_int tmp[1];
- #else
- mp_int* tmp = NULL;
- #endif
- /* Validate parameters. */
- if (BN_IS_NULL(bn) || (n < 0)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- /* Check if bit is set to clear. */
- if ((ret == 1) && (mp_is_bit_set((mp_int*)bn->internal, n))) {
- #ifdef WOLFSSL_SMALL_STACK
- /* Allocate a new MP integer to hold bit to clear. */
- tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (tmp == NULL) {
- ret = 0;
- }
- #endif
- if (ret == 1) {
- /* Reset new MP integer. */
- XMEMSET(tmp, 0, sizeof(mp_int));
- if (mp_init(tmp) != MP_OKAY) {
- ret = 0;
- }
- }
- /* Set the bit to clear into temporary MP integer. */
- if ((ret == 1) && (mp_set_bit(tmp, n) != MP_OKAY)) {
- ret = 0;
- }
- /* Clear bit by sutraction. */
- if ((ret == 1) && (mp_sub((mp_int*)bn->internal, tmp,
- (mp_int*)bn->internal) != MP_OKAY)) {
- ret = 0;
- }
- /* Free any dynamic memory in MP integer. */
- mp_clear(tmp);
- #ifdef WOLFSSL_SMALL_STACK
- /* Dispose of temporary MP integer. */
- XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
- #endif
- }
- return ret;
- }
- /* Returns whether the bit is set in the value of the big number.
- *
- * When bn is NULL, returns 0.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] bn Big number to check.
- * @param [in] n Inidex of bit to check.
- * @return 1 if bit set.
- * @return 0 otherwise.
- */
- int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n)
- {
- int ret;
- /* Check for big number value. */
- if (BN_IS_NULL(bn) || (n < 0)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- else {
- /* Set bit with wolfCrypt. */
- ret = mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n);
- }
- return ret;
- }
- /* Set the big number to the value 0.
- *
- * @param [in, out] bn Big number to use.
- */
- void wolfSSL_BN_zero(WOLFSSL_BIGNUM* bn)
- {
- /* Validate parameter. */
- if (!BN_IS_NULL(bn)) {
- /* Set wolfCrypt representation to 0. */
- mp_zero((mp_int*)bn->internal);
- }
- }
- /* Set the big number to the value 0.
- *
- * @param [in, out] bn Big number to use.
- * @return 1 on success.
- * @return 0 when bn or internal representation of bn is NULL.
- */
- int wolfSSL_BN_one(WOLFSSL_BIGNUM* bn)
- {
- int ret;
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- ret = 0;
- }
- else {
- /* Set to value one. */
- ret = wolfSSL_BN_set_word(bn, 1);
- }
- return ret;
- }
- /* Get the value of the MP integer as a word.
- *
- * Assumes the MP integer value will fit in a word.
- *
- * @param [in] mp MP integer.
- * @return Value of MP integer as an unsigned long.
- */
- static WOLFSSL_BN_ULONG wolfssl_bn_get_word_1(mp_int *mp) {
- #if DIGIT_BIT >= (SIZEOF_LONG * CHAR_BIT)
- return (WOLFSSL_BN_ULONG)mp->dp[0];
- #else
- WOLFSSL_BN_ULONG ret = 0UL;
- unsigned int i;
- for (i = 0; i < (unsigned int)mp->used; ++i) {
- ret |= ((WOLFSSL_BN_ULONG)mp->dp[i]) << (DIGIT_BIT * i);
- }
- return ret;
- #endif
- }
- /* Return the value of big number as an unsigned long if possible.
- *
- * @param [in] bn Big number to get value from.
- * @return Value or 0xFFFFFFFFL if bigger than unsigned long.
- */
- WOLFSSL_BN_ULONG wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_BN_ULONG ret;
- WOLFSSL_ENTER("wolfSSL_BN_get_word");
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("Invalid argument");
- ret = 0;
- }
- /* Check whether big number is to fit in an unsigned long. */
- else if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) {
- WOLFSSL_MSG("bignum is larger than unsigned long");
- ret = WOLFSSL_BN_MAX_VAL;
- }
- else {
- /* Get the word from the internal representation. */
- ret = wolfssl_bn_get_word_1((mp_int*)bn->internal);
- }
- return ret;
- }
- /* Set the big number to the value in the word.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in, out] bn Big number to set.
- * @param [in w Word to set.
- * @return 1 on success.
- * @return 0 when bn is NULL or setting value failed.
- */
- int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, unsigned long w)
- {
- int ret = 1;
- WOLFSSL_ENTER("wolfSSL_BN_set_word");
- /* Validate parameters. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- /* Set the word into the internal representation. */
- if ((ret == 1) && (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY)) {
- WOLFSSL_MSG("mp_init_set_int error");
- ret = 0;
- }
- return ret;
- }
- /*******************************************************************************
- * Comparison APIs
- ******************************************************************************/
- /* Compares two big numbers. a <=> b
- *
- * NULL equals NULL
- * NULL less than not NULL
- * not NULL greater than NULL.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] bn First big number to compare.
- * @param [in] bn Second big number to compare.
- * @return -1 when a is less than b (a < b).
- * @return 0 when a is equal to b (a == b).
- * @return 1 when a is greater than b (a > b).
- * @return 0 when bn or internal representation of bn is NULL.
- */
- int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
- {
- int ret;
- int bIsNull;
- WOLFSSL_ENTER("wolfSSL_BN_cmp");
- /* Must know whether b is NULL. */
- bIsNull = BN_IS_NULL(b);
- /* Check whether a is NULL. */
- if (BN_IS_NULL(a)) {
- if (bIsNull) {
- /* NULL equals NULL. */
- ret = 0;
- }
- else {
- /* NULL less than not NULL. */
- ret = -1;
- }
- }
- else if (bIsNull) {
- /* not NULL greater than NULL. */
- ret = 1;
- }
- else {
- /* Compare big numbers with wolfCrypt. */
- ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal);
- /* Convert wolfCrypt return value. */
- if (ret == MP_EQ) {
- ret = 0;
- }
- else if (ret == MP_GT) {
- ret = 1;
- }
- else {
- ret = -1;
- }
- }
- return ret;
- }
- /* Indicates whether a big number is the value 0.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] bn Big number to use.
- * @return 1 when number is zero.
- * @return 0 when number is not zero.
- * @return 0 when bn or internal representation of bn is NULL.
- */
- int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_is_zero");
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- ret = 0;
- }
- else {
- /* wolfCrypt checks whether value is 0. */
- ret = (mp_iszero((mp_int*)bn->internal) == MP_YES);
- }
- return ret;
- }
- /* Indicates whether a big number is the value 1.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] bn Big number to use.
- * @return 1 when number is one.
- * @return 0 when number is not one.
- * @return 0 when bn or internal representation of bn is NULL.
- */
- int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_is_one");
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- ret = 0;
- }
- else {
- /* wolfCrypt checks whether value is 1. */
- ret = (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ);
- }
- return ret;
- }
- /* Indicates whether a big number is the value passed in.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] bn Big number to use.
- * @return 1 when big number is the value.
- * @return 0 when big number is not the value.
- * @return 0 when bn or internal representation of bn is NULL.
- */
- int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_is_word");
- /* Validate parameter. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- else
- #if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT)
- /* When value is greater than what can be stored in one digit - special
- * case. */
- if (w > (WOLFSSL_BN_ULONG)MP_MASK) {
- /* TODO: small stack */
- mp_int w_mp;
- /* Create a MP to hold the number. */
- if (mp_init(&w_mp) != MP_OKAY) {
- ret = 0;
- }
- /* Set the value - held in more than one digit. */
- else if (mp_set_int(&w_mp, w) != MP_OKAY) {
- ret = 0;
- }
- else {
- /* Compare MP representations. */
- ret = (mp_cmp((mp_int *)bn->internal, &w_mp) == MP_EQ);
- mp_free(&w_mp);
- }
- }
- else
- #endif
- {
- /* wolfCrypt checks whether it is the value. */
- ret = (mp_isword((mp_int*)bn->internal, (mp_digit)w) == MP_YES);
- }
- return ret;
- }
- /*******************************************************************************
- * Word operation APIs.
- ******************************************************************************/
- /* Add/subtract a word to/from a big number.
- *
- * Internal function for adding/subtracting an unsigned long from a
- * WOLFSSL_BIGNUM. To add, pass "sub" as 0. To subtract, pass it as 1.
- *
- * @param [in, out] bn Big number to operate on.
- * @param [in] w Word to operate with.
- * @param [in] sub Indicates whether operation to perform is a subtract.
- * @return 1 on success.
- * @return 0 in failure.
- */
- static int wolfssl_bn_add_word_int(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w,
- int sub)
- {
- int ret = 1;
- #if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT)
- #ifdef WOLFSSL_SMALL_STACK
- mp_int* w_mp = NULL;
- #else
- mp_int w_mp[1];
- #endif /* WOLFSSL_SMALL_STACK */
- #endif
- #if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT)
- #ifdef WOLFSSL_SMALL_STACK
- /* Allocate temporary MP integer. */
- w_mp = (mp_int*)XMALLOC(sizeof(*w_mp), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (w_mp == NULL) {
- ret = 0;
- }
- else
- #endif /* WOLFSSL_SMALL_STACK */
- {
- /* Clear out MP integer so it can be freed. */
- XMEMSET(w_mp, 0, sizeof(*w_mp));
- }
- #endif
- /* Validate parameters. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- if (ret == 1) {
- int rc = 0;
- #if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT)
- if (w > (WOLFSSL_BN_ULONG)MP_MASK) {
- /* Initialize temporary MP integer. */
- if (mp_init(w_mp) != MP_OKAY) {
- ret = 0;
- }
- /* Set value into temporary MP integer. */
- if ((ret == 1) && (mp_set_int(w_mp, w) != MP_OKAY)) {
- ret = 0;
- }
- if (ret == 1) {
- if (sub) {
- /* Subtract as MP integer. */
- rc = mp_sub((mp_int *)bn->internal, w_mp,
- (mp_int *)bn->internal);
- }
- else {
- /* Add as MP integer. */
- rc = mp_add((mp_int *)bn->internal, w_mp,
- (mp_int *)bn->internal);
- }
- if (rc != MP_OKAY) {
- WOLFSSL_MSG("mp_add/sub error");
- ret = 0;
- }
- }
- }
- else
- #endif
- {
- if (sub) {
- /* Subtract word from MP integer. */
- rc = mp_sub_d((mp_int*)bn->internal, (mp_digit)w,
- (mp_int*)bn->internal);
- }
- else {
- /* Add word from MP integer. */
- rc = mp_add_d((mp_int*)bn->internal, (mp_digit)w,
- (mp_int*)bn->internal);
- }
- if (rc != MP_OKAY) {
- WOLFSSL_MSG("mp_add/sub_d error");
- ret = 0;
- }
- }
- }
- #if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT)
- mp_free(w_mp);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(w_mp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif /* WOLFSSL_SMALL_STACK */
- #endif
- return ret;
- }
- /* Add a word to a big number.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in, out] bn Big number to operate on.
- * @param [in] w Word to operate with.
- * @return 1 on success.
- * @return 0 in failure.
- */
- int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_add_word");
- ret = wolfssl_bn_add_word_int(bn, w, 0);
- WOLFSSL_LEAVE("wolfSSL_BN_add_word", ret);
- return ret;
- }
- /* Subtract a word from a big number.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in, out] bn Big number to operate on.
- * @param [in] w Word to operate with.
- * @return 1 on success.
- * @return 0 in failure.
- */
- int wolfSSL_BN_sub_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_sub_word");
- ret = wolfssl_bn_add_word_int(bn, w, 1);
- WOLFSSL_LEAVE("wolfSSL_BN_sub_word", ret);
- return ret;
- }
- #if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || \
- !defined(NO_DSA))
- /* Calculate bn modulo word w. bn % w
- *
- * Return code compliant with OpenSSL.
- *
- * @return Word result on success
- * @return -1 on error
- */
- WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn,
- WOLFSSL_BN_ULONG w)
- {
- WOLFSSL_BN_ULONG ret = 0;
- WOLFSSL_ENTER("wolfSSL_BN_mod_word");
- /* Validate parameters. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = (WOLFSSL_BN_ULONG)-1;
- }
- #if DIGIT_BIT < (SIZEOF_LONG * CHAR_BIT)
- if ((ret == 0) && (w > (WOLFSSL_BN_ULONG)MP_MASK)) {
- /* TODO: small stack */
- mp_int w_mp;
- mp_int r_mp;
- /* Memset MP integers to be safe to free. */
- XMEMSET(&w_mp, 0, sizeof(w_mp));
- XMEMSET(&r_mp, 0, sizeof(r_mp));
- /* Initialize MP integer to hold word. */
- if (mp_init(&w_mp) != MP_OKAY) {
- ret = (WOLFSSL_BN_ULONG)-1;
- }
- /* Initialize MP integer to hold result word. */
- if ((ret == 0) && (mp_init(&r_mp) != MP_OKAY)) {
- ret = (WOLFSSL_BN_ULONG)-1;
- }
- /* Set modulus word into MP integer. */
- if ((ret == 0) && (mp_set_int(&w_mp, w) != MP_OKAY)) {
- ret = (WOLFSSL_BN_ULONG)-1;
- }
- /* Calculate modulus result. */
- if ((ret == 0) && (mp_mod((mp_int *)bn->internal, &w_mp, &r_mp) !=
- MP_OKAY)) {
- WOLFSSL_MSG("mp_mod error");
- ret = (WOLFSSL_BN_ULONG)-1;
- }
- if (ret == 0) {
- /* Get modulus result into an unsigned long. */
- ret = wolfssl_bn_get_word_1(&r_mp);
- }
- /* Dispose of dynamically allocated data. */
- mp_free(&r_mp);
- mp_free(&w_mp);
- }
- else
- #endif
- if (ret == 0) {
- mp_digit mp_ret;
- /* Calculate modulus result using wolfCrypt. */
- if (mp_mod_d((mp_int*)bn->internal, (mp_digit)w, &mp_ret) != MP_OKAY) {
- WOLFSSL_MSG("mp_add_d error");
- ret = (WOLFSSL_BN_ULONG)-1;
- }
- else {
- /* Return result. */
- ret = (WOLFSSL_BN_ULONG)mp_ret;
- }
- }
- return ret;
- }
- #endif /* WOLFSSL_KEY_GEN && (!NO_RSA || !NO_DH || !NO_DSA) */
- /*******************************************************************************
- * Shift APIs
- ******************************************************************************/
- #ifndef WOLFSSL_SP_MATH
- /* Shift the value in bn left by n bits into r. r = bn << n
- *
- * Return code compliant with OpenSSL.
- *
- * @return 1 on success.
- * @return 0 when r or bn or internal representation is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
- {
- int ret = 1;
- WOLFSSL_ENTER("wolfSSL_BN_lshift");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- else if (n < 0) {
- WOLFSSL_MSG("n value error");
- ret = 0;
- }
- /* Use wolfCrypt perform operation. */
- if ((ret == 1) && (mp_mul_2d((mp_int*)bn->internal, n,
- (mp_int*)r->internal) != MP_OKAY)) {
- WOLFSSL_MSG("mp_mul_2d error");
- ret = 0;
- }
- return ret;
- }
- /* Shift the value in bn right by n bits into r. r = bn >> n
- *
- * Return code compliant with OpenSSL.
- *
- * @return 1 on success.
- * @return 0 when r or bn or internal representation is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
- {
- int ret = 1;
- WOLFSSL_ENTER("wolfSSL_BN_rshift");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- else if (n < 0) {
- WOLFSSL_MSG("n value error");
- ret = 0;
- }
- /* Use wolfCrypt perform operation. */
- if ((ret == 1) && (mp_div_2d((mp_int*)bn->internal, n, (mp_int*)r->internal,
- NULL) != MP_OKAY)) {
- WOLFSSL_MSG("mp_mul_2d error");
- ret = 0;
- }
- return ret;
- }
- #endif
- /*******************************************************************************
- * Simple Math APIs
- ******************************************************************************/
- /* Add a to b into r. r = a + b
- *
- * Return code compliant with OpenSSL.
- *
- * @param [out] r Big number to put result into.
- * @param [in] a Big number to be added to.
- * @param [in] b Big number to add with.
- *
- * @return 1 on success.
- * @return 0 when r, a or b or internal representation is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b)
- {
- int ret = 1;
- WOLFSSL_ENTER("wolfSSL_BN_add");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- /* Add the internal representations into internal representation. */
- if ((ret == 1) && (mp_add((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)r->internal) != MP_OKAY)) {
- WOLFSSL_MSG("mp_add_d error");
- ret = 0;
- }
- return ret;
- }
- /* Subtract a from b into r. r = a - b
- *
- * @param [out] r Big number to put result into.
- * @param [in] a Big number to be subtracted from.
- * @param [in] b Big number to subtract with.
- *
- * @return 1 on success.
- * @return 0 when r, a or b is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
- const WOLFSSL_BIGNUM* b)
- {
- int ret = 1;
- WOLFSSL_ENTER("wolfSSL_BN_sub");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
- ret = 0;
- }
- /* Have wolfCrypt perform operation with internal representations. */
- if ((ret == 1) && (mp_sub((mp_int*)a->internal,(mp_int*)b->internal,
- (mp_int*)r->internal) != MP_OKAY)) {
- ret = 0;
- }
- WOLFSSL_LEAVE("wolfSSL_BN_sub mp_sub", ret);
- return ret;
- }
- /* Multiply a with b into r. r = a * b
- *
- * @param [out] r Big number to put result into.
- * @param [in] a Big number to be multiplied.
- * @param [in] b Big number to multiply with.
- * @param [in] ctx BN context object. Unused.
- *
- * @return 1 on success.
- * @return 0 when r, a or b is NULL.
- * @return 0 when internal representation of r, a or b is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_mul(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b,
- WOLFSSL_BN_CTX *ctx)
- {
- int ret = 1;
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_mul");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
- ret = 0;
- }
- /* Have wolfCrypt perform operation with internal representations. */
- if ((ret == 1) && (mp_mul((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)r->internal) != MP_OKAY)) {
- ret = 0;
- }
- WOLFSSL_LEAVE("wolfSSL_BN_mul", ret);
- return ret;
- }
- #ifndef WOLFSSL_SP_MATH
- /* Divide a by b into dv and put remainder into rem. dv = a / b, rem = a % b
- *
- * @param [out] dv Big number to put division result into.
- * @param [out] rem Big number to put remainder into.
- * @param [in] a Big number to be divided.
- * @param [in] b Big number to divide with.
- * @param [in] ctx BN context object. Unused.
- *
- * @return 1 on success.
- * @return 0 when dv, rem, a or b is NULL.
- * @return 0 when internal representation of dv, rem, a or b is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_div(WOLFSSL_BIGNUM* dv, WOLFSSL_BIGNUM* rem,
- const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* d, WOLFSSL_BN_CTX* ctx)
- {
- int ret = 1;
- WOLFSSL_BIGNUM* res = dv;
- /* BN context not needed. */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_div");
- if (BN_IS_NULL(res)) {
- res = wolfSSL_BN_new();
- }
- /* Validate parameters. */
- if (BN_IS_NULL(res) || BN_IS_NULL(rem) || BN_IS_NULL(a) || BN_IS_NULL(d)) {
- ret = 0;
- }
- /* Have wolfCrypt perform operation with internal representations. */
- if ((ret == 1) && (mp_div((mp_int*)a->internal, (mp_int*)d->internal,
- (mp_int*)res->internal, (mp_int*)rem->internal) != MP_OKAY)) {
- ret = 0;
- }
- if (res != dv)
- wolfSSL_BN_free(res);
- WOLFSSL_LEAVE("wolfSSL_BN_div", ret);
- return ret;
- }
- #endif
- /* Calculate a mod b into r. r = a % b
- *
- * @param [out] r Big number to put result into.
- * @param [in] a Big number to reduced
- * @param [in] b Big number to reduce with.
- * @param [in] ctx BN context object. Unused.
- *
- * @return 1 on success.
- * @return 0 when r, a or b is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
- const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c)
- {
- int ret = 1;
- (void)c;
- WOLFSSL_ENTER("wolfSSL_BN_mod");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
- ret = 0;
- }
- /* Have wolfCrypt perform operation with internal representations. */
- if ((ret == 1) && (mp_mod((mp_int*)a->internal,(mp_int*)b->internal,
- (mp_int*)r->internal) != MP_OKAY)) {
- ret = 0;
- }
- WOLFSSL_LEAVE("wolfSSL_BN_mod mp_mod", ret);
- return ret;
- }
- /*******************************************************************************
- * Math and Mod APIs
- ******************************************************************************/
- #ifndef WOLFSSL_SP_MATH
- /* Add a to b modulo m into r. r = a + b (mod m)
- *
- * @param [in, out] r Big number to hold result.
- * @param [in] a Big number to add to.
- * @param [in] b Big number to add with.
- * @param [in] m Big number that is the modulus.
- * @param [in] ctx BN context. Not used.
- * @return 1 on success.
- * @return 0 when r, a or b or internal representation is NULL.
- * @return 0 on calculation failure.
- */
- int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
- const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
- {
- int ret = 1;
- /* BN context not needed. */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_add");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b) || BN_IS_NULL(m)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- /* Perform operation with wolfCrypt. */
- if ((ret == 1) && (mp_addmod((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)m->internal, (mp_int*)r->internal) != MP_OKAY)) {
- WOLFSSL_MSG("mp_add_d error");
- ret = 0;
- }
- return ret;
- }
- #endif
- /* Calculate a multiplied by b, mod m into r. r = (a * b) % m
- *
- * @param [out] r Big number to put result into.
- * @param [in] a Base as a big number.
- * @param [in] b Multiplier as a big number.
- * @param [in] m Modulus as a big number.
- * @param [in] ctx BN context object. Unused.
- *
- * @return 1 on success.
- * @return 0 when r, a, b or m is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
- const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
- {
- int ret = 1;
- /* BN context not needed. */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_mod_mul");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b) || BN_IS_NULL(m)) {
- WOLFSSL_MSG("Bad Argument");
- ret = 0;
- }
- /* Have wolfCrypt perform operation with internal representations. */
- if ((ret == 1) && (mp_mulmod((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)m->internal, (mp_int*)r->internal)) != MP_OKAY) {
- ret = 0;
- }
- WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret);
- return ret;
- }
- /* Calculate a to the power of e, mod m into r. r = (a ^ e) % m
- *
- * @param [out] r Big number to put result into.
- * @param [in] a Base as a big number.
- * @param [in] e Exponent as a big number.
- * @param [in] m Modulus as a big number.
- * @param [in] ctx BN context object. Unused.
- *
- * @return 1 on success.
- * @return 0 when r, a, p or m is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
- const WOLFSSL_BIGNUM *e, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
- {
- int ret = 1;
- /* BN context not needed. */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_mod_exp");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(e) || BN_IS_NULL(m)) {
- WOLFSSL_MSG("Bad Argument");
- ret = 0;
- }
- /* Have wolfCrypt perform operation with internal representations. */
- if ((ret == 1) && (mp_exptmod((mp_int*)a->internal, (mp_int*)e->internal,
- (mp_int*)m->internal, (mp_int*)r->internal)) != MP_OKAY) {
- ret = 0;
- }
- WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret);
- return ret;
- }
- /* Calculate the modular inverse of a mod m into r. r = a^-1 mod m
- *
- * A new big number is allocated when r is NULL.
- *
- * @param [in, out] r Big number to hold result. May be NULL.
- * @param [in] a Big number to invert.
- * @param [in] m Big number that is the modulus.
- * @param [in] ctx BN context. Not used.
- * @return Big number holding result on success.
- * @return NULL on failure.
- */
- WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a,
- const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
- {
- int err = 0;
- WOLFSSL_BIGNUM* t = NULL;
- /* BN context not needed. */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_mod_inverse");
- /* Validate parameters. */
- if (BN_IS_NULL(a) || BN_IS_NULL(m) || ((r != NULL) &&
- (r->internal == NULL))) {
- WOLFSSL_MSG("a or n NULL error");
- err = 1;
- }
- /* Check whether we have a result big number. */
- if ((!err) && (r == NULL)) {
- /* Allocate a new big number to hold result and be returned. */
- t = wolfSSL_BN_new();
- if (t == NULL){
- WOLFSSL_MSG("WolfSSL_BN_new() failed");
- err = 1;
- }
- r = t;
- }
- /* Compute inverse of a modulo n and return in r */
- if ((!err) && (mp_invmod((mp_int *)a->internal, (mp_int *)m->internal,
- (mp_int*)r->internal) != MP_OKAY)) {
- WOLFSSL_MSG("mp_invmod() error");
- err = 1;
- }
- if (err) {
- wolfSSL_BN_free(t);
- r = NULL;
- }
- return r;
- }
- /*******************************************************************************
- * Other Math APIs
- ******************************************************************************/
- #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)
- /* Needed to get mp_gcd. */
- /* Greatest Common Divisor (GCM) of a and b into r. r = GCD(a, b)
- *
- * @param [out] r Big number to put result into.
- * @param [in] a First big number.
- * @param [in] b Second big number.
- * @param [in] ctx BN context object. Unused.
- *
- * @return 1 on success.
- * @return 0 when r, a or b is NULL.
- * @return 0 when internal representation of r, a or b is NULL.
- * @return 0 on failure.
- */
- int wolfSSL_BN_gcd(WOLFSSL_BIGNUM* r, WOLFSSL_BIGNUM* a, WOLFSSL_BIGNUM* b,
- WOLFSSL_BN_CTX* ctx)
- {
- int ret = 1;
- /* BN context not needed. */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_gcd");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(a) || BN_IS_NULL(b)) {
- ret = 0;
- }
- /* Have wolfCrypt perform operation with internal representations. */
- if ((ret == 1) && (mp_gcd((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)r->internal) != MP_OKAY)) {
- ret = 0;
- }
- WOLFSSL_LEAVE("wolfSSL_BN_gcd", ret);
- return ret;
- }
- #endif /* !NO_RSA && WOLFSSL_KEY_GEN */
- /*******************************************************************************
- * Random APIs
- ******************************************************************************/
- /* Generates a random number up to bits long.
- *
- * @param [in, out] bn Big number to generate into.
- * @param [in] bits Number of bits in word.
- * @param [in] top Whether top bits must be set.
- * Valid values: WOLFSSL_BN_RAND_TOP_ANY,
- * WOLFSSL_BN_RAND_TOP_ONE, WOLFSSL_BN_RAND_TOP_TWO.
- * @param [in] bottom Whether bottom bit must be set.
- * Valid values: WOLFSSL_BN_RAND_BOTTOM_ANY,
- WOLFSSL_BN_RAND_BOTTOM_ODD.
- * @return 1 on success.
- * @return 0 when bn is NULL.
- * @return 0 when bits is invalid.
- * @return 0 when bits and top/bottom are invalid.
- * @return 0 when generation fails.
- */
- int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
- {
- int ret = 1;
- word32 len = (word32)((bits + 7) / 8);
- WC_RNG* rng;
- WOLFSSL_ENTER("wolfSSL_BN_rand");
- /* Validate parameters. */
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("Bad argument - bn");
- ret = 0;
- }
- else if (bits < 0) {
- WOLFSSL_MSG("Bad argument - bits < 0");
- ret = 0;
- }
- else if ((bits == 0) && ((bottom != WOLFSSL_BN_RAND_BOTTOM_ANY) ||
- (top != WOLFSSL_BN_RAND_TOP_ANY))) {
- WOLFSSL_MSG("Bad top/bottom - bits == 0");
- ret = 0;
- }
- else if ((bits == 1) && (top > WOLFSSL_BN_RAND_TOP_ONE)) {
- WOLFSSL_MSG("Bad top - bits == 1");
- ret = 0;
- }
- /* Handle simple case of zero bits. */
- if ((ret == 1) && (bits == 0)) {
- mp_zero((mp_int*)bn->internal);
- }
- else if (ret == 1) {
- byte* buff = NULL;
- /* Get random to global random to generate bits. */
- if ((rng = wolfssl_make_global_rng()) == NULL) {
- WOLFSSL_MSG("Failed to use global RNG.");
- ret = 0;
- }
- /* Allocate buffer to hold generated bits. */
- if ((ret == 1) && ((buff = (byte*)XMALLOC(len, NULL,
- DYNAMIC_TYPE_TMP_BUFFER)) == NULL)) {
- WOLFSSL_MSG("Failed to allocate buffer.");
- ret = 0;
- }
- /* Generate bytes to cover bits. */
- if ((ret == 1) && wc_RNG_GenerateBlock(rng, buff, len) != 0) {
- WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
- ret = 0;
- }
- /* Read bytes in to big number. */
- if ((ret == 1) && mp_read_unsigned_bin((mp_int*)bn->internal, buff, len)
- != MP_OKAY) {
- WOLFSSL_MSG("mp_read_unsigned_bin failed");
- ret = 0;
- }
- /* Dispose of buffer - no longer needed. */
- XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret == 1) {
- /* Truncate to requested bit length. */
- mp_rshb((mp_int*)bn->internal, 8 - (bits % 8));
- }
- /* Set top bit when required. */
- if ((ret == 1) && (top >= WOLFSSL_BN_RAND_TOP_ONE) &&
- (mp_set_bit((mp_int*)bn->internal, bits - 1) != MP_OKAY)) {
- WOLFSSL_MSG("Failed to set top bit");
- ret = 0;
- }
- /* Set second top bit when required. */
- if ((ret == 1) && (top > WOLFSSL_BN_RAND_TOP_ONE) &&
- (mp_set_bit((mp_int*)bn->internal, bits - 2) != MP_OKAY)) {
- WOLFSSL_MSG("Failed to set second top bit");
- ret = 0;
- }
- /* Set bottom bit when required. */
- if ((ret == 1) && (bottom == WOLFSSL_BN_RAND_BOTTOM_ODD) &&
- (mp_set_bit((mp_int*)bn->internal, 0) != MP_OKAY)) {
- WOLFSSL_MSG("Failed to set 0th bit");
- ret = 0;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_BN_rand", ret);
- return ret;
- }
- /* Generates a pseudo-random number up to bits long.
- *
- * Implemented using wolfSSL_BN_rand().
- *
- * @param [in, out] bn Big number to generate into.
- * @param [in] bits Number of bits in word.
- * @param [in] top Whether top bits must be set.
- * Valid values: WOLFSSL_BN_RAND_TOP_ANY,
- * WOLFSSL_BN_RAND_TOP_ONE, WOLFSSL_BN_RAND_TOP_TWO.
- * @param [in] bottom Whether bottom bit must be set.
- * Valid values: WOLFSSL_BN_RAND_BOTTOM_ANY,
- WOLFSSL_BN_RAND_BOTTOM_ODD.
- * @return 1 on success.
- * @return 0 when bn is NULL.
- * @return 0 when bits is invalid.
- * @return 0 when bits and top/bottom are invalid.
- * @return 0 when generation fails.
- */
- int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
- {
- return wolfSSL_BN_rand(bn, bits, top, bottom);
- }
- /* Maximum number of trials to attempt at generating a number in range. */
- #define RANGE_MAX_TRIALS 100
- /* Generate big number to be a value between 0 and range-1.
- *
- * N = length of range input var
- *
- * Generate N-bit length numbers until generated number is less than range
- * @param [in] r Big number to generate into.
- * @param [in] range The upper limit of generated number.
- * @return 1 on success.
- * @return 0 on failure.
- */
- int wolfSSL_BN_rand_range(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *range)
- {
- int ret = 1;
- WOLFSSL_ENTER("wolfSSL_BN_rand_range");
- /* Validate parameters. */
- if (BN_IS_NULL(r) || BN_IS_NULL(range)) {
- WOLFSSL_MSG("Bad parameter");
- ret = 0;
- }
- if (ret == 1) {
- /* Calculate number of bits in modulus. */
- int n = wolfSSL_BN_num_bits(range);
- if (n <= 1) {
- /* Modulus is 0 or 1. */
- wolfSSL_BN_zero(r);
- }
- else {
- int i;
- /* Try generating a number in range for a limited number of trials.
- */
- for (i = 0; (ret == 1) && (i < RANGE_MAX_TRIALS); i++) {
- /* Generate a random number in range. */
- if (wolfSSL_BN_pseudo_rand(r, n, WOLFSSL_BN_RAND_TOP_ANY,
- WOLFSSL_BN_RAND_BOTTOM_ANY) == 0) {
- WOLFSSL_MSG("wolfSSL_BN_rand error");
- ret = 0;
- }
- /* Check if in range. */
- else if (wolfSSL_BN_cmp(r, range) < 0) {
- break;
- }
- }
- /* Fail if max trial attempts made. */
- if (i >= RANGE_MAX_TRIALS) {
- WOLFSSL_MSG("wolfSSL_BN_rand_range too many iterations");
- ret = 0;
- }
- }
- }
- return ret;
- }
- /*******************************************************************************
- * Prime APIs
- ******************************************************************************/
- #if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || \
- !defined(NO_DSA))
- /* Generate a prime number.
- *
- * @param [in, out] prime Big number to generate into.
- * @param [in] bits Number of bits in generated number.
- * @param [in] safe Whether number must be a safe prime.
- * @param [in] add Value to add when generating. Not used.
- * @param [in] rem Remainder of number modulo add. Not used.
- * @param [in] cb Generation callback. Not used.
- * @return 1 on success.
- * @return 0 when prime is NULL.
- * @return 0 when safe required or add or rem is not NULL.
- * @return 0 on generation failure.
- */
- int wolfSSL_BN_generate_prime_ex(WOLFSSL_BIGNUM* prime, int bits,
- int safe, const WOLFSSL_BIGNUM* add, const WOLFSSL_BIGNUM* rem,
- WOLFSSL_BN_GENCB* cb)
- {
- int ret = 1;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
- #else
- WC_RNG tmpRng[1];
- #endif
- WC_RNG* rng = NULL;
- int localRng = 0;
- /* Callback not used. */
- (void)cb;
- WOLFSSL_ENTER("wolfSSL_BN_generate_prime_ex");
- /* Check unsupported parameters. */
- if ((safe == 1) || (add != NULL) || (rem != NULL)) {
- ret = 0;
- }
- /* Validate parameters. */
- else if (BN_IS_NULL(prime)) {
- ret = 0;
- }
- /* Create a new RNG or use global. */
- if ((ret == 1) && ((rng = wolfssl_make_rng(tmpRng, &localRng)) == NULL)) {
- ret = 0;
- }
- /* Use wolfCrypt to generate a prime. */
- if ((ret == 1) && (mp_rand_prime((mp_int*)prime->internal, (bits + 7) / 8,
- rng, NULL) != MP_OKAY)) {
- ret = 0;
- }
- if (localRng) {
- /* Dispose of local RNG that was created. */
- wc_FreeRng(rng);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
- #endif
- }
- WOLFSSL_LEAVE("wolfSSL_BN_generate_prime_ex", ret);
- return ret;
- }
- /* Check whether a big number is prime.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] bn Big number to check.
- * @param [in] checks Number of Miller-Rabin tests to perform.
- * @param [in] ctx BN context. Not used.
- * @param [in] cb Generation callback. Not used.
- * @return 1 when number is prime.
- * @return 0 when number is not prime.
- * @return -1 when bn is NULL or failure when checking.
- */
- int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int checks,
- WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb)
- {
- int ret = 1;
- WC_RNG* rng = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
- #else
- WC_RNG tmpRng[1];
- #endif
- int localRng = 0;
- int res = MP_NO;
- /* BN context not needed. */
- (void)ctx;
- (void)cb;
- WOLFSSL_ENTER("wolfSSL_BN_is_prime_ex");
- if (BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = -1;
- }
- /* Create a new RNG or use global. */
- if ((ret == 1) && ((rng = wolfssl_make_rng(tmpRng, &localRng)) == NULL)) {
- ret = -1;
- }
- if ((ret == 1) && (mp_prime_is_prime_ex((mp_int*)bn->internal, checks, &res,
- rng) != MP_OKAY)) {
- WOLFSSL_MSG("mp_prime_is_prime_ex error");
- ret = -1;
- }
- if (localRng) {
- wc_FreeRng(rng);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
- #endif
- }
- if ((ret != -1) && (res != MP_YES)) {
- WOLFSSL_MSG("mp_prime_is_prime_ex not prime");
- ret = 0;
- }
- return ret;
- }
- #endif /* WOLFSSL_KEY_GEN && (!NO_RSA || !NO_DH || !NO_DSA) */
- /*******************************************************************************
- * Print APIs
- ******************************************************************************/
- #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) && \
- defined(XFPRINTF)
- /* Print big number to file pointer.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] fp File pointer.
- * @param [in] bn Big number to print.
- * @return 1 on success.
- * @return 0 when fp is a bad file pointer.
- * @return 0 when bn is NULL.
- * @return 0 when creating hex string fails.
- * @return 0 when printing fails.
- */
- int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn)
- {
- int ret = 1;
- char* buf = NULL;
- WOLFSSL_ENTER("wolfSSL_BN_print_fp");
- /* Validate parameters. */
- if ((fp == XBADFILE) || BN_IS_NULL(bn)) {
- WOLFSSL_MSG("bn NULL error");
- ret = 0;
- }
- /* Create a hex string of big number. */
- if ((ret == 1) && ((buf = wolfSSL_BN_bn2hex(bn)) == NULL)) {
- WOLFSSL_MSG("wolfSSL_BN_bn2hex failure");
- ret = 0;
- }
- /* Print hex string to file pointer. */
- if ((ret == 1) && (XFPRINTF(fp, "%s", buf) < 0)) {
- ret = 0;
- }
- /* Dispose of any allocated data. */
- XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
- return ret;
- }
- #endif /* !NO_FILESYSTEM && XFPRINTF */
- /*******************************************************************************
- * BN_CTX APIs
- ******************************************************************************/
- /* Allocate and return a new BN context object.
- *
- * BN context not needed for operations.
- *
- * @return Pointer to dummy object.
- */
- WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void)
- {
- /* wolfcrypt doesn't need BN context. */
- static int ctx;
- WOLFSSL_ENTER("wolfSSL_BN_CTX_new");
- return (WOLFSSL_BN_CTX*)&ctx;
- }
- /* Initialize a BN context object.
- *
- * BN context not needed for operations.
- *
- * @param [in] ctx Dummy BN context.
- */
- void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx)
- {
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_CTX_init");
- }
- /* Free a BN context object.
- *
- * BN context not needed for operations.
- *
- * @param [in] ctx Dummy BN context.
- */
- void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx)
- {
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_CTX_free");
- /* Don't do anything since using dummy, static BN context. */
- }
- /* Get a big number based on the BN context.
- *
- * @param [in] ctx BN context. Not used.
- * @return Big number on success.
- * @return NULL on failure.
- */
- WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx)
- {
- /* ctx is not used - returning a new big number. */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_CTX_get");
- /* Return a new big number. */
- return wolfSSL_BN_new();
- }
- #ifndef NO_WOLFSSL_STUB
- /* Start stack of temporary big numbers.
- *
- * Newly allocated big numbers are returned instead of having a stack.
- *
- * @param [in] ctx BN context. Not used.
- */
- void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx)
- {
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_CTX_start");
- WOLFSSL_STUB("BN_CTX_start");
- WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD");
- }
- #endif
- #endif /* OPENSSL_EXTRA */
- #endif /* !WOLFSSL_SSL_BN_INCLUDED */
|